← 返回题目列表

如何判断一棵二叉树是否对称(轴对称)?

高频 简单 第 4 / 30 题 更新于 2026/07/29
二叉树对称递归

简化版

一棵树对称,等价于它的左子树和右子树互为镜像。递归比较两棵子树:两个根值要相等,且左树的左孩子对右树的右孩子、左树的右孩子对右树的左孩子(外侧配外侧、内侧配内侧)。只要每一对都镜像匹配,整棵树就对称。也能用队列迭代,成对入队比较。

详细版

关键:对称不是「左子树等于右子树」,而是「左子树和右子树互为镜像」。镜像意味着比较时要交叉

boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    return isMirror(root.left, root.right);
}
boolean isMirror(TreeNode a, TreeNode b) {
    if (a == null && b == null) return true;       // 都空,镜像
    if (a == null || b == null) return false;      // 一空一非空,不镜像
    return a.val == b.val                          // 根值相等
        && isMirror(a.left,  b.right)              // 外侧:a的左 对 b的右
        && isMirror(a.right, b.left);              // 内侧:a的右 对 b的左
}

以这棵对称树为例:

      1
     / \
    2   2
   / \ / \
  3  4 4  3

比较左 2 和右 2:值相等;左2的左(3) 对 右2的右(3)✓;左2的右(4) 对 右2的左(4)✓。全部匹配,对称。

完整版教学

一、为什么是「交叉比较」而不是「同侧比较」

轴对称的含义是「以根为轴,左右翻折后能完全重合」。翻折后,左子树的最外侧会和右子树的最外侧重合,左子树的内侧和右子树的内侧重合。落到节点上就是:

  • 左子树的孩子 ↔ 右子树的孩子(外对外)
  • 左子树的孩子 ↔ 右子树的孩子(内对内)

所以递归时是交叉匹配 (a.left, b.right)(a.right, b.left),而不是 (a.left, b.left)。这是本题最核心、也最容易写错的地方。

二、递归的三种情况

比较两个节点 a、b 是否镜像:

  1. 都为空:镜像成立(对称位置都没节点)。
  2. 一个空一个非空:结构不对称,返回 false。
  3. 都非空:值必须相等,且左右交叉的两对子节点也各自镜像。

递归出口是前两种,第三种把问题分解到更小的子问题。

三、迭代解法:成对入队

用队列,每次成对取出应当镜像的两个节点比较:

boolean isSymmetric(TreeNode root) {
    if (root == null) return true;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root.left); q.offer(root.right);
    while (!q.isEmpty()) {
        TreeNode a = q.poll(), b = q.poll();
        if (a == null && b == null) continue;
        if (a == null || b == null || a.val != b.val) return false;
        q.offer(a.left);  q.offer(b.right);   // 外侧一对
        q.offer(a.right); q.offer(b.left);    // 内侧一对
    }
    return true;
}

入队顺序保证每次 poll 出来的两个正好是「应当镜像」的一对。注意入队顺序仍是交叉的(a.leftb.right)。

四、和「相同的树」「翻转」的关系

  • 判断两棵树相同:对应位置同侧比较 (a.left,b.left)(a.right,b.right),值都相等。
  • 判断对称:一棵树的左右子树交叉比较(互为镜像)。
  • 翻转二叉树:把树改成镜像。

三者是一组「围绕镜像/相等」的题:判断对称 = 判断「左子树 和 翻转后的右子树 是否相同」。理解一个就能推出其他。

五、复杂度

  • 时间 O(n):每个节点被比较一次。
  • 空间 O(h):递归栈深度为树高(迭代版是队列宽度 O(w))。

六、常见误区与追问

题型比较方式是否修改树
相同的树同侧比较:左对左、右对右不修改
对称二叉树交叉比较:左对右、右对左不修改
翻转二叉树每个节点交换左右孩子修改结构

记忆钩子:对称不是「左右子树长得一样」,而是「左子树照镜子后等于右子树」。

  • 误区:判断对称时同侧比较左右孩子。 同侧比较是判断两棵树是否相同;对称必须交叉比较外侧和内侧。
  • 误区:只比较结构不比较节点值。 镜像要求结构对应且节点值相等,少任意一个条件都不成立。
  • 误区:判断对称需要先翻转一棵子树。 可以这么想,但实现上通常直接递归比较镜像位置,避免修改原树。
  • 追问:空树是否对称? 通常认为空树对称;根为空直接返回 true
  • 追问:迭代版为什么要成对入队? 每次出队的两个节点是一组镜像候选,必须同时比较空值、节点值和下一层交叉孩子。
  • 追问:复杂度是多少? 时间 O(n),每个节点最多比较一次;递归空间 O(h),迭代队列最坏 O(w)。

七、加强记忆

树对称 ⟺ 左右子树互为镜像。递归比较两节点:值相等,且交叉匹配——左树的左对右树的右(外对外)、左树的右对右树的左(内对内)。交叉是关键,别写成同侧。也可用队列成对入队比较。它和「判断相同树(同侧比较)」「翻转」是一组镜像题。时间 O(n)。