@Leetcode对称二叉树
作为一道稍有进阶的数据结构经典题,对称二叉树的使用着实费了小白笔者不少脑筋。我一直在想能不能用先序后序遍历的方法解决,即在一棵树上做出判断,然而实际上解法并非如此。卖个关子,请看题干:
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
说明:
如果你可以运用递归和迭代两种方法解决这个问题,会很加分。
虽然说题目已经暗示了有两种方法解决这个问题——递归和迭代,但是笔者脑子依然是一团浆糊,先入为主的思想真是十分该死,那么到头来到底这题的递归解法应该怎么写?请看代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return judge(root,root);
}
bool judge(TreeNode* t1, TreeNode* t2) {
if(t1==NULL&&t2==NULL)
return true;
else if(t1==NULL||t2==NULL)
return false;
else
return (t1->val==t2->val)
&&judge(t1->left,t2->right)
&&judge(t1->right,t2->left);
}
};
刚看到这个想法的时候,笔者确实也不得其要领,但是当你把一棵树当成两棵树来看待,这就不一样了。
要解决这棵树是否是对称的,我们首先要了解镜像对称,又称手性对称的概念。这种对称模型就像你照镜子,或者你的两只手一样,是相对另一半的反方向对称的,即在镜子里的你的右边是你的左边,在镜子里的你的左边是你的右边。
那么同理,如果要这棵树是对称的,不妨创造另外一棵在镜子里的树,只要原有的这棵树的左子树与镜像树的右子树完全相同,镜像树的左子树也与原有的树的右子树相同,并且根结点相同,说明这棵树确实是对称的。
那么总结一下就是需要满足两个条件:第一,两棵树的根结点必须相同(可以同时为空,说明是一棵空树);第二,对应方向的左子树必须与右子树完全相等(右子树与左子树完全相等)。当这两个条件同时满足的时候就可以解决问题。
与之对应的代码如上,需要注意的是,要先判断返回true的双空情况,再判断其中一个为空的情况,因为双空情况不是已经都没有子树了就是整个为空树,这两种情况是一定可得证为正确情况的,而其中一个为空,就如第二个示例,是不可能正确的。再这两种情况都不满足的时候就是比较环节了,与之前判断相同的树时类似,使用短路运算能节省很多的运算步骤和不需要的代码:如果两个结点相等,这也是必须满足的第一个条件,再进行判断接下来的递归条件,必选其一,最终得到答案。
那么还有一种迭代的方法呢?说实话,其实迭代的方法认真思考之下是更容易想到的,无非就是我开两个队列,分别存储两个子树的每一个子节点并按顺序pop比较一下,请看代码:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> q1;
queue<TreeNode*> q2;
q1.push(root);
q2.push(root);
while(!q1.empty()&&!q2.empty()){
TreeNode* t1=q1.front();
TreeNode* t2=q2.front();
q1.pop();
q2.pop();
if (t1==NULL&&t2==NULL) continue;
if (t1==NULL||t2==NULL) return false;
if (t1->val!=t2->val) return false;
q1.push(t1->left);
q2.push(t2->right);
q1.push(t1->right);
q2.push(t2->left);
}
return true;
}
};
迭代法参上!确实开了两个队列解决问题(实际上一个队列也能解决,只是开两个要明晰一些),要注意队列的定义和几个方法的使用,笔者在这上面CE了好多次,注意pop金近是出队头元素,并不能取得头元素的值。后面push的顺序一定要注意,要按照正确的比较顺序push这一层的结点才能起到比较镜像的作用。值得一提的是,最后有一个返回true可别丢了,否则正确的情况会在循环里不停地continue出不来,那是真的很尴尬。