题目描述

✅ 剑指 Offer 27. 二叉树的镜像

image-20261001230752550

image-20260928194611485

image-20260928194611486

题意分析

返回给定二叉树的镜像:从根到任一节点的路径上,原来向左的选择改为向右,原来向右的选择改为向左。节点值和节点数量都不变,变化的是每个节点左右孩子的位置。

当前实现直接修改输入树的连接关系,返回的仍是原根节点。空树的镜像仍为空,只有一侧孩子的节点也需要交换,不能只处理左右孩子都存在的情况。

解法:递归交换左右子树

核心思路

[!blue]

对任意子树,镜像后的左子树应当是原右子树的镜像,右子树应当是原左子树的镜像。这个定义在整棵树与任一子树上都相同,因此适合递归。

约定 mirrorTree(root) 原地完成以 root 为根的整棵子树的镜像,并返回这个根。先交换当前节点的左右孩子,确定这一层的新方向;再分别递归处理交换后的两个孩子,让它们内部也全部镜像。

空节点直接返回,叶子的两个空孩子交换后仍为空。从最底层向上看,只要两个子树内部已经按递归约定镜像,配合当前层的交换就得到整棵子树的正确镜像,最终覆盖所有节点。

Java 交换前必须保存原来的左孩子,避免连续赋值时丢失其中一棵子树;Go 的多重赋值会先读取两个旧引用。交换的是引用,不是节点值,因此整个子树会随孩子引用一起移动。

解题步骤

  1. 若 root 为空,直接返回空引用。
  2. 用临时变量或多重赋值交换 root.left 与 root.right,空孩子也参与交换。
  3. 递归镜像交换后的左子树和右子树,每一侧只处理一次。
  4. 返回当前根节点。所有修改已经发生在原树上,不需要重新构造节点。

代码实现

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        // 先保存原左子树,再交换两条引用,避免覆盖后丢失节点。
        TreeNode left = root.left;

        root.left = root.right;
        root.right = left;
        // 当前层交换后,继续镜像两个完整子树。
        mirrorTree(root.left);
        mirrorTree(root.right);

        return root;
    }
}
func mirrorTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }

    // 交换孩子引用后,继续镜像两个完整子树。
    root.Left, root.Right = root.Right, root.Left
    mirrorTree(root.Left)
    mirrorTree(root.Right)
    return root
}

复杂度分析

  • 时间复杂度:$O(n)$,每个节点恰好交换一次左右孩子。
  • 空间复杂度:$O(h)$,h 为树高,来自递归栈;平衡树为 $O(\log n)$,链状树最坏为 $O(n)$。

关键点总结

[!green]

  • 先明确递归函数的语义,再按“当前节点操作 + 子问题”写代码。
  • 返回值仍是原根节点,输入树的孩子引用已经被修改。
  • 交换引用必须用临时变量或多重赋值,不能连续覆盖。

易错点总结

[!yellow]

  • 连续写 root.left = root.right; root.right = root.left:原左子树引用已丢失,两个孩子会指向同一节点。
  • 只交换根节点:三层树的更深层仍保持原方向,必须递归到每个节点。
  • 交换后又递归旧引用且重复其中一侧:可能导致一棵子树翻转两次、另一棵未翻转;应统一递归交换后的两个孩子。
  • 忘记空节点出口:叶子节点继续递归时会触发空指针异常。
  • 忽略原地修改语义:调用结束后输入树本身已经改变,后续若仍依赖原结构会得到错误结果。

相似题目

题目 难度 关联与区别
101. 对称二叉树 简单 对称性可以看作原树与镜像相同,本题实际生成镜像结构。
156. 上下翻转二叉树 中等 原题把最左链向上翻转并改变父子关系,本题只在每个节点交换左右孩子。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2022/98031428
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!