如何翻转(镜像)一棵二叉树?
简化版
翻转二叉树就是把每个节点的左右孩子对调。递归做法只有三步:交换当前节点的左右孩子,再分别递归翻转左子树和右子树。几行代码搞定,本质是对每个节点都做一次「左右互换」。也能用 BFS/迭代,对队列或栈里取出的每个节点交换左右孩子。
详细版
TreeNode invertTree(TreeNode root) {
if (root == null) return null;
// 交换左右孩子
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// 递归翻转左右子树
invertTree(root.left);
invertTree(root.right);
return root;
}
效果:
1 1
/ \ / \
2 3 → 3 2
/ \ / \
4 5 5 4
翻转后,整棵树变成原来的镜像。递归的「交换」放在递归左右子树之前(前序)或之后(后序)都可以,只要每个节点都被交换一次即可。
完整版教学
一、问题本质:每个节点做一次左右互换
「翻转/镜像二叉树」听起来抽象,拆开看就是:对树里的每一个节点,把它的 left 和 right 交换。所有节点都换完,整棵树就镜像了。所以核心动作是「交换左右孩子」,剩下的只是「怎么遍历到每个节点」——递归、BFS、DFS 迭代都行。
二、递归解法为什么优雅
递归天然「访问到每个节点」。对当前节点:先交换它的左右孩子,然后递归地让左子树、右子树也各自翻转。递归出口是空节点(直接返回)。这就是一个标准的树遍历 + 在每个节点上做一件事(交换)。
交换和递归的先后顺序不影响结果:
- 前序(先交换,再递归左右):交换后递归的 left 已经是原来的 right,但因为我们对两棵子树都会翻转,结果一致。
- 后序(先递归左右,再交换):先把两棵子树各自翻转好,再把它俩换位置,结果也一致。
三、迭代解法(BFS / DFS)
不想用递归(怕深树栈溢出)时,可以用队列或栈遍历,对每个取出的节点交换左右孩子:
TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Deque<TreeNode> stack = new ArrayDeque<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
TreeNode t = node.left; node.left = node.right; node.right = t; // 交换
if (node.left != null) stack.push(node.left);
if (node.right != null) stack.push(node.right);
}
return root;
}
把 stack(栈)换成 queue(队列)就是 BFS 版,效果相同——因为无论什么顺序,只要每个节点都被交换一次即可。
四、易错点
- 别忘了返回值/根节点:翻转是原地修改,根节点不变,最后返回 root。
- 交换要用临时变量,否则
root.left = root.right会先把 left 覆盖掉。 - 递归出口别漏
if (root == null) return。
五、延伸:翻转 vs 判断对称
「翻转二叉树」和「判断二叉树是否对称」是一对相关题:
- 翻转:把树改成它的镜像。
- 判断对称:判断一棵树是否「本身就等于自己的镜像」(左子树和右子树互为镜像)。
两者思路相通,都是围绕「镜像」展开,常一起考。
六、常见误区与追问
| 解法 | 遍历顺序 | 是否原地修改 | 适合说明 |
|---|---|---|---|
| 递归 DFS | 前序或后序都可 | 是 | 代码最短,表达「每个节点交换左右」 |
| 迭代 BFS | 队列层序 | 是 | 避免递归栈,过程更直观 |
| 迭代 DFS | 栈 | 是 | 和 BFS 类似,只是访问顺序不同 |
记忆钩子:翻转二叉树不是改变遍历序列,而是对每个真实节点执行一次
left和right指针交换。
- 误区:只交换根节点的左右子树就完成了翻转。 根节点交换只处理了一层,子树内部的每个节点也要继续交换。
- 误区:递归必须用后序。 本题交换当前节点与递归左右子树没有依赖关系,前序、后序都能正确;关键是每个节点都访问一次。
- 误区:翻转会新建一棵树。 常见实现是原地修改指针并返回原根节点;除非题目要求保留原树,才需要复制节点。
- 追问:时间和空间复杂度是多少? 时间 O(n),每个节点交换一次;空间是 O(h) 递归栈,迭代 BFS 最坏队列可到 O(w),w 是最大层宽。
- 追问:翻转和判断对称有什么关系? 翻转是修改树结构;判断对称是比较左右子树是否镜像,通常不需要真的翻转。
- 追问:空树和单节点怎么处理? 空树直接返回
null,单节点交换两个空孩子后仍是自己,都是自然边界。
七、加强记忆
翻转二叉树 = 对每个节点交换左右孩子。递归三步:交换当前节点左右、递归翻左、递归翻右(交换放递归前后都行)。也可用栈/队列迭代,对每个取出的节点交换。注意用临时变量交换、返回根节点。它和「判断对称(树是否等于自己的镜像)」是相关的一对题。时间 O(n)。