Leetcode(101)——对称二叉树
题目
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
提示:
- 树中节点数目在范围 [1, 1000] 内
- -100 <= Node.val <= 100
进阶:你可以运用 递归 和 迭代 两种方法解决这个问题吗?
题解
方法一:递归
思路
如果一个树的左子树与右子树镜像对称,那么这个树是对称的。

因此,该问题可以转化为:两个树在什么情况下互为镜像?
如果同时满足下面的条件,两个树互为镜像:
- 它们的两个根结点具有相同的值
- 每个树的右子树都与另一个树的左子树镜像对称

我们可以实现这样一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,ppp 指针和 qqq 指针一开始都指向这棵树的根,随后 ppp 右移时,qqq 左移,ppp 左移时,qqq 右移。每次检查当前 ppp 和 qqq 节点的值是否相等,如果相等再判断左右子树是否对称。
代码实现
我的
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return compareTree(root->left, root->right);
}
bool compareTree(TreeNode* root1, TreeNode* root2){
if( root1 != nullptr && root2 != nullptr && root1->val == root2->val){
if( compareTree(root1->right, root2->left) && compareTree(root1->left, root2->right) )
return true;
else return false;
}else if(root1 == nullptr && root2 == nullptr) return true;
else return false;
}
};
Leetcode 官方题解
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);
}
};
复杂度分析
时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)O(n)O(n)。假设树上一共 nnn 个节点。
空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 nnn,故渐进空间复杂度为 O(n)O(n)O(n)。假设树上一共 nnn 个节点。
方法二:迭代
思路
「方法一」中我们用递归的方法实现了对称性的判断,那么如何用迭代的方法实现呢?首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。
代码实现
我的
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
// 迭代
queue<TreeNode*> root1, root2; // 用于回溯
if(root->left != nullptr && root->right != nullptr){
root1.push(root->left);
root2.push(root->right);
}else if(root->left == nullptr && root->right == nullptr) return true;
else return false;
// 层序遍历
while(!root1.empty() && !root2.empty()){
if(root1.front() == nullptr && root2.front() == nullptr){
// 只出队列
root1.pop();
root2.pop();
}else if(root1.front()->val == root2.front()->val){
// 出队列,入其非空的左右子树,注意 root1 和 root2 顺序要相反
if(root1.front()->left != nullptr && root2.front()->right != nullptr){
root1.push(root1.front()->left);
root2.push(root2.front()->right);
}else if(root1.front()->left == nullptr && root2.front()->right == nullptr){
root1.push(nullptr);
root2.push(nullptr);
}else return false;
if(root1.front()->right != nullptr && root2.front()->left != nullptr){
root1.push(root1.front()->right);
root2.push(root2.front()->left);
}else if(root1.front()->right == nullptr && root2.front()->left == nullptr){
root1.push(nullptr);
root2.push(nullptr);
}else return false;
root1.pop();
root2.pop();
}else return false;
}
return true;
}
};
Leetcode 官方题解
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);
}
};
复杂度分析
时间复杂度:O(n)O(n)O(n),同「方法一」。
空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 nnn 个点,故渐进空间复杂度为 O(n)O(n)O(n)。
本文介绍了一种判断二叉树是否对称的方法,包括递归和迭代两种实现方式,并详细解析了每种方法的代码实现及复杂度分析。


573

被折叠的 条评论
为什么被折叠?



