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
进阶:你可以运用递归和迭代两种方法解决这个问题吗?
解法
方法一:递归
我们设计一个函数 \(dfs(root1, root2)\),用于判断两个二叉树是否对称。答案即为 \(dfs(root, root)\)。
函数 \(dfs(root1, root2)\) 的逻辑如下:
- 如果 \(root1\) 和 \(root2\) 都为空,则两个二叉树对称,返回
true
; - 如果 \(root1\) 和 \(root2\) 中只有一个为空,或者 \(root1.val \neq root2.val\),则两个二叉树不对称,返回
false
; - 否则,判断 \(root1\) 的左子树和 \(root2\) 的右子树是否对称,以及 \(root1\) 的右子树和 \(root2\) 的左子树是否对称,这里使用了递归。
时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)。其中 \(n\) 是二叉树的节点数。
方法二:非递归迭代
「方法一」中我们用递归的方法实现了对称性的判断,那么如何用迭代的方法实现呢?首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。
时间复杂度:\(O(n)\),同「方法一」。
空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 \(n\) 个点,故渐进空间复杂度为 \(O(n)\)。
Python3
递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def dfs(self,root1,root2):
if not root1 and not root2:
return True
elif not root1 or not root2:
return False
elif root1.val != root2.val:
return False
else:
return self.dfs(root1.left,root2.right) and self.dfs(root1.right,root2.left)
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
return self.dfs(root.left,root.right)
迭代
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def check(self,u,v):
q = deque([])
q.append(u)
q.append(v)
while(q):
u = q.popleft()
v = q.popleft()
if(not u and not v):
continue
if((not u or not v) or (u.val != v.val)):
return False
q.append(u.left)
q.append(v.right)
q.append(u.right)
q.append(v.left)
return True
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
return self.check(root.left,root.right)
C++
递归
/**
* 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 dfs(TreeNode* root1,TreeNode* root2){
if(!root1 && !root2)
return true;
else if(!root1 ||!root2)
return false;
else if(root1->val != root2->val)
return false;
else
return dfs(root1->left,root2->right) && dfs(root1->right,root2->left);
}
bool isSymmetric(TreeNode* root) {
return dfs(root->left,root->right);
}
};
迭代
/**
* 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;
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->left,root->right);
}
};