题目描述
给定一个二叉树的根节点 root,检查它是否轴对称(镜像对称)。
示例1:
1
/ \
2 2
/ \ / \
3 4 4 3
输入:root = [1,2,2,3,4,4,3]
输出:true
示例2:
1
/ \
2 2
\ \
3 3
输入:root = [1,2,2,null,3,null,3]
输出:false
问题理解
判断二叉树是否轴对称,意味着我们需要检查这棵树是否是自身的镜像。换句话说,对于树中的每个节点:
-
左子树和右子树的结构必须对称
-
对应位置的节点值必须相等
核心思路
思路一:递归法(深度优先搜索)
递归是最直观的解法。对于两棵树是否对称,我们可以定义递归规则:
python
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def recur(left:TreeNode,right:TreeNode)->bool:
if not left and not right:#左右都空
return True
if not left or not right or left.val!=right.val:#有一个为空或值不相等
return False
return recur(left.left,right.right) and recur(left.right,right.left)
return recur(root.left,root.right) or not root #考虑根为空
递归终止条件:
-
两个节点都为空 → 对称
-
一个为空一个不为空 → 不对称
-
两个节点值不相等 → 不对称
递归过程:
比较左子树的左节点与右子树的右节点,以及左子树的右节点与右子树的左节点。
思路二:迭代法(广度优先搜索)
递归可能会因为树深度过大导致栈溢出,因此我们可以使用迭代法。迭代法通常使用队列或栈来实现:
使用队列(BFS风格)
python
from collections import deque
def is_symmetric_iterative(root):
if not root:
return True
queue = deque()
queue.append((root.left, root.right))
while queue:
left, right = queue.popleft()
if not left and not right:
continue
if not left or not right or left.val != right.val:
return False
queue.append((left.left, right.right))
queue.append((left.right, right.left))
return True
使用栈(DFS风格)
python
def is_symmetric_stack(root):
if not root:
return True
stack = [(root.left, root.right)]
while stack:
left, right = stack.pop()
if not left and not right:
continue
if not left or not right or left.val != right.val:
return False
stack.append((left.left, right.right))
stack.append((left.right, right.left))
return True
算法分析
时间复杂度
- 所有方法的时间复杂度都是 O(n),其中 n 是树中节点的数量。每个节点最多被访问一次。
空间复杂度
-
递归法:O(h),其中 h 是树的高度。空间消耗来自递归调用栈。
-
迭代法(队列/栈):O(n),在最坏情况下(完全二叉树),队列/栈中需要存储大约 n/2 个节点。
方法对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 递归法 | 代码简洁,逻辑清晰 | 可能栈溢出(树很深时) | 树深度不大时 |
| 迭代法(队列) | 不会栈溢出,适合深树 | 代码稍复杂,需要额外空间 | 树深度很大时 |
| 迭代法(栈) | 模拟递归过程,直观 | 同队列法,需要额外空间 | 树深度很大时 |
常见误区
-
只比较值不比较结构:对称性不仅要求值相等,还要求结构对称。例如,左子树的左节点必须与右子树的右节点对应。
-
忽略空节点:空节点也需要参与比较。两个空节点是对称的,但一个空一个不空就是不对称的。
-
只检查直接子节点:需要递归检查整个子树,而不仅仅是直接子节点。
扩展思考
如何判断两棵树是否相同?
将对称判断的代码稍作修改即可:
python
def is_same_tree(p, q):
if not p and not q:
return True
if not p or not q or p.val != q.val:
return False
return is_same_tree(p.left, q.left) and is_same_tree(p.right, q.right)
如何获取树的镜像?
通过递归交换左右子树:
python
def mirror_tree(root):
if not root:
return None
# 交换左右子树
root.left, root.right = root.right, root.left
# 递归处理子树
mirror_tree(root.left)
mirror_tree(root.right)
return root
总结
判断二叉树是否对称是一个经典的二叉树问题,考察了对二叉树遍历和递归的理解。本文介绍了三种解法:
-
递归法:最直观,代码简洁,适合面试快速实现。
-
迭代法(队列):广度优先,适合树深度较大的情况。
-
迭代法(栈):深度优先,模拟递归过程。
在实际应用中,可以根据具体情况选择合适的方法:
-
对于一般情况,递归法足够使用。
-
对于深度可能很大的树,建议使用迭代法避免栈溢出。
掌握这个问题的解法,不仅有助于解决类似二叉树问题,还能加深对递归、树遍历等核心算法思想的理解。