题目描述
给定一个二叉树,判断它是否是自己的“镜像”(是否以中心竖线为轴左右对称)。
注意:如果同时给出递归和迭代方法,会获得加分。
样例1
如下二叉树 [1,2,2,3,4,4,3]
是自己的“镜像”:
1
/ \
2 2
/ \ / \
3 4 4 3
样例2
如下二叉树 [1,2,2,null,3,null,3]
不是自己的“镜像”:
1
/ \
2 2
\ \
3 3
算法1
(递归) $O(n)$
递归判断两个子树是否互为镜像。
两个子树互为镜像当且仅当:
- 两个子树的根节点值相等;
- 第一棵子树的左子树和第二棵子树的右子树互为镜像,且第一棵子树的右子树和第二棵子树的左子树互为镜像;
时间复杂度分析:从上到下每个节点仅被遍历一遍,所以时间复杂度是 $O(n)$。
C++ 代码
/**
* 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 !root || dfs(root->left, root->right);
}
bool dfs(TreeNode*p, TreeNode*q)
{
if (!p || !q) return !p && !q;
return p->val == q->val && dfs(p->left, q->right) && dfs(p->right, q->left);
}
};
算法2
(迭代) $O(n)$
用栈模拟递归,对根节点的左子树,我们用中序遍历;对根节点的右子树,我们用反中序遍历。
则两个子树互为镜像,当且仅当同时遍历两课子树时,对应节点的值相等。
时间复杂度分析:树中每个节点仅被遍历一遍,所以时间复杂度是 $O(n)$。
C++ 代码
/**
* 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) {
if (!root) return true;
stack<TreeNode*> left, right;
TreeNode *lc = root->left;
TreeNode *rc = root->right;
while(lc || rc || left.size())
{
while (lc && rc)
{
left.push(lc), right.push(rc);
lc = lc->left, rc = rc->right;
}
if (lc || rc) return false;
lc = left.top(), rc = right.top();
left.pop(), right.pop();
if (lc->val != rc->val) return false;
lc = lc->right, rc = rc->left;
}
return true;
}
};
y总,为什么while条件里不用加
right.size()
也能对呢?左右如果是对称的,left大小就等于right的大小,如果不对称,就在循环里return false了
我刚开始想的是如果是一棵对称树,那么按照左子树-根节点-右子树的顺序遍历和按照右子树-根节点-左子树的顺序遍历结果是一样的。通过了192/195个测试点,[1,2,2,2,null,2]这个测试点没有过。不知道大佬能否指出我的逻辑错误之处?
代码如下:
[1,2,2,2,null,2]
是二叉树的层序遍历,画出来之后可以发现,左右不对称,但是左根右和右根左的遍历结果是相同的。谢谢 我之前傻逼了