#226
简单
低频
递归法翻转二叉树
这是一道围绕树、二叉树展开的高频练习。建议先掌握「递归法」这套写法,再结合下方步骤讲解理解状态维护、边界处理和复杂度取舍。
树
二叉树
题目分析
给你一棵二叉树,要求把每个节点的左右子树交换过来,最终得到整棵树的镜像结构。
一句话概括:
对树中的每个节点都做一次“左右孩子交换”。
接下来怎么看推荐代码: 带着这个理解再看推荐代码时,重点观察这条主线:递归翻转左右子树,再把当前节点的左右孩子交换过来。
推荐代码
推荐解法:递归法
时间复杂度: O(n)
空间复杂度: O(h)
核心思路: 递归翻转左右子树,再把当前节点的左右孩子交换过来。
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.left = right;
root.right = left;
return root;
}
}结构化讲解
面试时怎么讲
开场思路
这题我会直接用递归,因为每个节点要做的事情完全一致:交换左右孩子。
核心过程
- 如果当前节点为空,直接返回。
- 递归翻转左子树和右子树。
- 把翻转后的左右子树交换位置挂回当前节点。
- 最终返回当前节点作为翻转后的子树根。
复杂度总结
时间复杂度 O(n),空间复杂度 O(h)。
面试补一句:这题最值得强调的是“每个节点执行同一动作”,所以递归定义非常干净。
核心思路
翻转二叉树的本质是对每个节点做同一件小事:交换左右孩子。因为每棵子树都和整棵树同构,所以递归写法最自然。
步骤讲解
1
空节点直接返回
节点为空时,没有任何孩子需要交换,递归就此结束。
为什么这样做:这是递归的边界条件,也是叶子节点向上回传的基础。
对应代码提示:if (root == null) return null;
2
先递归翻转左右子树
分别对左子树和右子树执行同样的翻转逻辑。
为什么这样做:每个子树本身也是一棵二叉树,问题结构完全一致。
对应代码提示:TreeNode left = invertTree(root.left); TreeNode right = invertTree(root.right);
3
交换当前节点左右孩子
把翻转后的左右子树互换位置,再挂回当前节点。
为什么这样做:当前层的翻转动作就是把左右方向完全互换。
对应代码提示:root.left = right; root.right = left;
易错点
只交换当前层,不递归子树
这样只能翻转根节点这一层,整棵树不会完全镜像。
正确理解:交换之前或之后,都要继续递归处理左右子树。
交换时直接覆盖导致丢失一边
如果没先保存引用,可能先写掉一边孩子再也取不回。
正确理解:先保存或先递归出左右结果,再交换赋值。
把返回值忽略掉
递归函数返回的是翻转后的子树根节点,忽略它会让连接关系出错。
正确理解:明确接收左右子树的递归返回值后再赋回。
复杂度与适用判断
时间复杂度:O(n)
空间复杂度:O(h)
比其他方案更好在哪里:比层序遍历迭代法更短,更贴近这题的递归结构。
适用判断:树上每个节点都要执行相同局部操作时,优先考虑递归 DFS。
额外提醒
- 翻转动作只发生在当前节点,但必须递归传播到整棵树。