给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3]
是对称的。
但是下面这个 [1,2,2,null,3,null,3]
则不是镜像对称的:
进阶:
你可以运用递归和迭代两种方法解决这个问题吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:
//对称二叉树——递归实现
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root != nullptr) {
return helper(root->left, root->right);
}
else {
return true;
}
}
bool helper(TreeNode* leftTree, TreeNode* rightTree) {
if (leftTree == nullptr && rightTree == nullptr) {
return true;
}
else if (leftTree != nullptr && rightTree != nullptr) {
if (leftTree->val != rightTree->val) {
return false;
}
return helper(leftTree->left, rightTree->right) && helper(leftTree->right, rightTree->left);
}
else {//两个树,只有一个是Null
return false;
}
}
};
递归函数helper
实现的是两棵树是否呈镜像。
边界条件是这两棵树都是空,那么返回true
。
对于一些特殊情况我们可以单独来考虑以提高效率:1.若只有一个树是空,那么返回false
; 2.若两个树都不为空但是根结点值不相等,那么返回false
。
剩余的是递归的情况:我们考虑这两棵树的子树的镜像情况:1.leftTree
的左子与rightTree
的右子是否呈镜像; 2.leftTree
的右子与rightTree
的左子是否呈镜像。之后返回其相与的布尔值即可。
其实和我的思路是一样的,只不过这个官方代码是更加简洁的。
class Solution {
public:
bool check(TreeNode *p, TreeNode *q) {
if (!p && !q) return true;
if (!p || !q) return false;
return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
//迭代实现——通过中序遍历
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (root == nullptr) {
return true;
}
TreeNode* currentLeft = root->left;
TreeNode* currentRight = root->right;
stack<TreeNode*> stLeft;
stack<TreeNode*> stRight;
while ((currentLeft != nullptr || !stLeft.empty()) && (currentRight != nullptr || !stRight.empty())) {
while (currentLeft != nullptr && currentRight != nullptr) {
stLeft.push(currentLeft);
currentLeft = currentLeft->left;
stRight.push(currentRight);
currentRight = currentRight->right;
}
if (currentLeft == nullptr && currentRight == nullptr) {
currentLeft = stLeft.top();
stLeft.pop();
currentRight = stRight.top();
stRight.pop();
if (currentLeft->val != currentRight->val) {
return false;
}
currentLeft = currentLeft->right;
currentRight = currentRight->left;
}
else {
return false;
}
}
if (!(currentLeft != nullptr || !stLeft.empty()) && !(currentRight != nullptr || !stRight.empty())) {
return true;
}
else {
return false;
}
}
};
分析:若左子树通过左中右完成中序遍历,右子树通过右中左完成中序遍历,则两者在输出(出栈)时对应的值应该是一样的。否则说明不是镜像。
「方法一」中我们用递归的方法实现了对称性的判断,那么如何用迭代的方法实现呢?首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。
class Solution {
public:
bool check(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u); q.push(v);
while (!q.empty()) {
u = q.front(); q.pop();
v = q.front(); q.pop();
if (!u && !v) continue;
if ((!u || !v) || (u->val != v->val)) return false;
q.push(u->left);
q.push(v->right);
q.push(u->right);
q.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
注意队列的先进先出。