101. 对称二叉树(Symmetric Tree)¶
频次 ★★★ · 难度 🟢 · 高频:字节
题目¶
判断一棵二叉树是否轴对称(镜像对称)。
示例:
思路¶
递归比较:两棵树镜像对称的条件是——根节点值相等,且左树的左子树与右树的右子树镜像对称,左树的右子树与右树的左子树镜像对称。
将"判断一棵树是否对称"转化为"判断左右两棵子树是否镜像",递归函数接收两个节点 left 和 right,比较 left.left vs right.right 且 left.right vs right.left。
也可用队列迭代:每次入队两个节点(left.left 与 right.right、left.right 与 right.left),成对出队比较。
代码¶
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isMirror(root.left, root.right);
}
private boolean isMirror(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
if (left.val != right.val) return false;
return isMirror(left.left, right.right)
&& isMirror(left.right, right.left);
}
复杂度¶
- 时间:O(n) —— 每个节点访问一次
- 空间:O(height) —— 递归栈深度
边界条件¶
- 空树:返回 true
- 单节点:返回 true(左右子树都为空,镜像成立)
- 左右子树结构不对称(一个为空一个非空):返回 false
- 值相等但结构不对称(如反例中左右两个 2 的子树结构不同):返回 false
变式¶
- 迭代版:用队列成对入队比较,避免递归栈溢出
- N 叉树的对称:将子节点列表反转后比较
- 如果要求判断"翻转后是否相等":等价于本题——翻转后自比就是对称性判定
易错点¶
- 不能只比较
root.left.val == root.right.val就递归——必须比较"左的左 vs 右的右"和"左的右 vs 右的左"交叉匹配 - 空节点处理:
left == null && right == null返回 true 要先判断,否则后续left.val会 NPE - 不要为"值相等"写
if (left.val == right.val) return true;——值相等只是必要条件,还要继续查子树结构。写成"相等就返回 true"会误判:[1,2,2,3,4,5,6](根的两个孩子值都是 2,但各自子树 3,4 与 5,6 完全不镜像)会错误返回 true - 正确的结构是排除法:先判"都空 = 成功",再判两种失败(一空一不空、值不等),剩下的自然继续递归——只有
==成立时才"什么都不做"往下走,这正是"相等不是答案,只是通行证"
面试追问¶
- 迭代怎么写? 用队列,初始入队
(root.left, root.right),每次出队两个节点比较,再按交叉顺序入队子节点。展示对递归转迭代的掌握 - 和翻转二叉树的关系? 翻转二叉树后与原树相等等价于原树是对称二叉树。两者本质相同:226 是操作,101 是判定
关联题¶
- 同套路:226. 翻转二叉树 —— 翻转后自比等价于对称判定
- 进阶:100. 相同的树 —— 判断两棵树是否完全相同,递归逻辑更简单(直接比较而非交叉)
- 知识点:二叉树递归模板见二叉树