题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
解题思路
提到二叉树,想到的就是三种不同二叉树的遍历方法,即前序遍历、中序遍历和后序遍历。在这三种遍历算法中,都是先遍历左子结点在遍历右子结点。评定是否为一颗对称树,最好想到的就是前序遍历,如果我们在定义一种类似于前序遍历的遍历方法:即先遍历父结点,再遍历右子结点,最后遍历左子结点。以上图为例:第一幅图中前序遍历为8657675,按新定义遍历为8657675,这两个序列是一样的。而第二幅图中前序遍历为8657975,按新定义遍历为8957675,这两个序列是有差别的。
但是按照上述思路,下面这一情况就不满足了,如图:
这样的情况怎么解决呢?其实我们只要在遍历的时候把遇到的NULL指针也考虑进来就好了,就拿这幅图来说,前序遍历为[8 8 8 NULL NULL 8 NULL NULL 8 8 NULL NULL NULL],新定义遍历为[8 8 NULL 8 NULL NULL 8 8 NULL NULL 8 NULL 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 isSymmetrical(TreeNode* pRoot)
{
if(pRoot == NULL)
return true;
return Symmetrical(pRoot->left,pRoot->right);
}
bool Symmetrical(TreeNode* t1, TreeNode* t2) {
if(t1 == NULL && t2 == NULL) //如果左右子树都为空
return true;
if(t1 != NULL && t2 != NULL) //如果左右子树都不为空
return t1->val == t2->val && Symmetrical(t1->left,t2->right) && Symmetrical(t1->right, t2->left);
return false; //如果左右子树之一为空
}
};
非递归版
/*
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;
queue<TreeNode*> q1,q2;
TreeNode *left,*right;
q1.push(pRoot->left);
q2.push(pRoot->right);
while(!q1.empty() and !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;
}
};