101. 对称二叉树

简单 含交互动画

学完这道你应该能: 说清它为什么用「递归」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

判断二叉树是否轴对称(沿根的竖线翻折后左右重合)。

= 1 →(2,2),左2→(3,4),右2→(4,3)
输出 = true

思路解析

最直觉的想法:先复制整棵树、把每个节点的左右孩子翻转造出「镜像树」,再和原树一个一个比。能对,但要额外建一棵树、多走一遍,空间和代码都更重,纯属多此一举。

转折:对称的本质是「左子树」和「右子树」互为镜像,不必真造出镜像树,让一个递归同时握住左 L、右 R 两个节点对照走即可。规则:都空→对称;一空一非→不对称;否则要求 L.val==R.val,且 L 的左配 R 的右(外侧)、L 的右配 R 的左(内侧)。这题能这么做,是因为对称是「两两镜像位置」的局部判断,天然适合双节点同步递归。

出发 · 比根的两个孩子:根 1 自己不用比,直接拿它的左孩子 L=2 和右孩子 R=2 开镜像比较。两个都非空,先看值:2 == 2 ✓。转折点:不去真造镜像树,而是就让这一个递归同时握住 L、R 往下走。

值相等 · 拆出外侧、内侧两对:L=2、R=2 值相等后,对称要求交叉地往下递归两对:外侧 = L.left 配 R.right、内侧 = L.right 配 R.left。这两对都成立,整支才算镜像。先看外侧。

外侧配外侧 · L.left vs R.right:第一对外侧:左孩子的左 (3)右孩子的右 (3)——这是离中线最远的一对。注意是交叉取:左的 left 对右的 right。3 == 3 ✓,且两边都是叶子,这一对镜像成立。

内侧配内侧 · L.right vs R.left:第二对内侧:左孩子的右 (4)右孩子的左 (4)——靠近中线的一对,同样交叉取。4 == 4 ✓。外侧、内侧两对都成立,左 2 和右 2 这一支镜像完全通过。

左 2 这一支全部成立:左 2 与右 2 这一支:值相等、外侧相等、内侧相等,三项都成立,isMirror(左2, 右2) 返回 True。这棵小树只有这一支要比,根的两个孩子镜像即整树镜像。

处处相等 · 整棵对称:每一对镜像位置都相等,递归全程返回 True,整棵树对称。只要途中有一对不等或结构对不上,就会立刻短路返回 False。下面看看那种不对称的情况长什么样。

反例对照 · 把内侧右 4 改成 9:假设左孩子的右改成了 9。走到内侧这对:L.right=9R.left=49 != 4 。这一对镜像不成立。

一对不等 · 立刻 return False:只要任意一对镜像位置不相等,不必再比其余节点,直接 return False——递归靠 and 短路,一处假则全假。回到正例:正因为每一对都相等,才返回 True。

判断对称、判断两树相同、合并两棵树,都用「同时握住两个节点往下递归」的双指针式 DFS。对称就交叉(左配右)、相同就平行(左配左)——只差递归传参那一处。

参考代码(Python)

Python
1def isMirror(L, R):
2    if not L and not R: return True       # 都空,对称
3    if not L or not R: return False       # 一空一非,结构不对
4    return (L.val == R.val and             # 值要相等
5            isMirror(L.left, R.right) and  # 外侧: 左的左 配 右的右
6            isMirror(L.right, R.left))     # 内侧: 左的右 配 右的左
7return isMirror(root.left, root.right) if root else True

复杂度分析

  • 时间复杂度:O(n) —— 每对镜像节点比较一次,共约 n 个节点
  • 空间复杂度:O(h) —— 递归栈深度等于树高 h

套路模板

记住骨架:两个都空→真、一空一非→假、值等且子树两两递归。「相同的树(LC100)」把交叉改成平行 dfs(a.left,b.left) 就行。

Python
1def dfs(a, b):
2    if not a and not b: return True     # 都空
3    if not a or not b: return False     # 结构不一致
4    return (a.val == b.val                # 值相等
5            and dfs(a.left, b.right)              # 对称: 外侧对外侧
6            and dfs(a.right, b.left))             # 相同的树(LC100)改成平行 a.left,b.left

易错点

  • 错误写法:对称写成平行 isMirror(L.left, R.left)正确写法:对称要交叉 isMirror(L.left, R.right)(镜像是外侧配外侧、内侧配内侧,平行比就成了判「两边长得一样」而非「镜像」)
  • 错误写法:只比值不判空,遇 None 取 .val 报错正确写法:先判空:都空→真、一空一非→假(结构不同(一边有孩子一边没有)也算不对称,且不先挡住 None 会崩)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →543. 二叉树的直径 ← 返回题库