【剑指Offer】面试题59:对称二叉树

时间:2021-06-13 14:20:11

整理自剑指Offer

一:题目描述


请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。


二:解题思路


看到这个题第一反应是求二叉树的镜像二叉树,然后同时遍历两个树,进行比较

遇到问题 :在求二叉树的镜像二叉树改变了原始的二叉树的结构,不可行


剑指Offer的解法:

【剑指Offer】面试题59:对称二叉树

如上图,我们可以看出第一个二叉树是对称的,第二棵与第三棵是不对称的


对树的遍历有三种方式:前序遍历,中序遍历,后序遍历,在这三种方法中都是先遍历左子结点再遍历右子节点。

是否可以定义一种新的遍历方式,先遍历右子节点再遍历左子结点


如先序遍历:父结点,左子结点,右子节点

定义的基于先序遍历的新的遍历方式:父结点,右子节点,左子结点

如果两者输出的结果相同,则说明这个二叉树是对称的


如上图第一棵树:

先序遍历 8、6、5、7、6、7、5

新的遍历8、6、5、7、6、7、5

对称

第二棵树:

先序遍历:8、6、5、7、9、7、5

新的遍历:8、9、5、7、6、7、5

不对称

第三棵树

先序遍历:7、7、7、7、7、7

新的遍历:7、7、7、7、7、7

对称?不对


如何解决这个问题:将叶子节点的NULL加入其中就可以解决


第三棵树:

先序遍历:7、7、7、NULL、NULL、7、NULL、NULL、7、7、NULL、NULL、NULL

新的遍历:7、7、NULL、7、NULL、NULL、7、NULL、NULL、7、NULL、NULL

不对称



三:代码实现

递归版代码

/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:

bool isSymmetricalCore(TreeNode* pRoot1,TreeNode* pRoot2){

if(pRoot1==NULL && pRoot2==NULL)
return true;
if(pRoot1==NULL || pRoot2==NULL)
return false;
if(pRoot1->val!=pRoot2->val)
return false;
//阶梯思想容易理解,但是递归的代码不易理解
//可以将pRoot1看成是先序遍历的指针,先左后右
//可以将pRoot2看成是新的遍历的指针,先右后左
//如果两者相同,比较下一个对称位置的结点
//如果不相等,返回false
return isSymmetricalCore(pRoot1->left,pRoot2->right)&&
isSymmetricalCore(pRoot1->right,pRoot2->left);
}

bool isSymmetrical(TreeNode* pRoot)
{
//递归版本

//根节点为空指针,认为是对称的
if(pRoot==NULL)
return true;
return isSymmetricalCore(pRoot,pRoot);
}

};

非递归版代码--队列方式实现

/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{

if(pRoot==NULL)
return true;
//利用两个队列保存两种遍历的结果,队列先进先出
//q1:先序遍历结果 q2:新的遍历的结果
queue<TreeNode*>q1,q2;
TreeNode *left,*right;
//入队
q1.push(pRoot->left); //先左后右
q2.push(pRoot->right); //先右后左
while(!q1.empty() && !q2.empty()){

left=q1.front(); //取队首元素
q1.pop(); //出队
right=q2.front();
q2.pop();

//对称位置均空,继续
if(left==NULL && right==NULL)
continue;
//对称位置一空一不空,不对称
if(left==NULL || right==NULL)
return false;
//对称位置值不相同,不对称
if(left->val!=right->val)
return false;

q1.push(left->left);
q1.push(left->right);
q2.push(right->right);
q2.push(right->left);

}
return true;
}
};