总结
求解左右子树互为镜像
- 递归
- 迭代
给你一个二叉树的根节点 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
进阶:
- 你可以运用递归和迭代两种方法解决这个问题吗?
方法一 递归
思路与算法
如果一个树的左子树与右子树镜像对称,那么这个树是对称的。
因此,该问题可以转化为:两个树在什么情况下互为镜像?
如果同时满足下面的条件,两个树互为镜像:
- 它们的两个根结点具有相同的值
- 每个树的右子树都与另一个树的左子树镜像对称
递归函数的实现:通过「同步移动」两个指针的方法来遍历这棵树,p指针和q指针一开始都指向这棵树的根,随后p右移时,q左移,p左移时,q右移。每次检查当前p和q节点的值是否相等,如果相等再判断左右子树是否对称。
/**
* 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) {
return isMirror(root,root);
}
//通过递归判断两棵树是否对称
bool isMirror(TreeNode *p,TreeNode *q){
//两棵树同时为空,对称
if(!p && !q){
return true;
}
//一棵树为空,另一棵树不空,不对称
if(!p || !q){
return false;
}
//两棵树都为空
//要求1:两棵树本身根节点相同
//要求2:子树互为镜像
return(p->val==q->val && isMirror(p->right,q->left) && isMirror(p->left,q->right));
}
};
复杂度分析
假设树一共n个节点
- 时间复杂度:遍历树的渐进时间复杂度为 O ( n ) O(n) O(n)。
- 空间复杂度:空间复杂度和递归使用的栈空间有关,这里递归层数不超过n,故渐进空间复杂度为 O ( n ) O(n) O(n)。
方法二 迭代
思路与算法
「方法一」中我们用递归的方法实现了对称性的判断,那么如何用迭代的方法实现呢?
首先引入一个队列,这是把递归程序改写成迭代程序的常用方法。
初始化时把根节点入队两次。
每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像)
然后将两个结点的左右子结点按相反的顺序插入队列中。
当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。
/**
* 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 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;
//一边为空另一边非空,直接false
//镜像节点值不同的情况
//要求1: 镜像节点相同
if((!u || !v) || (u->val != v->val)){
return false;
}
//要求2:子树互为镜像
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);
}
};
复杂度分析
假设树一共n个节点
- 时间复杂度:遍历树的渐进时间复杂度为 O ( n ) O(n) O(n)。
- 空间复杂度:此方法用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n个点,故渐进空间复杂度为 O ( n ) O(n) O(n)。