题目描述
LeetCode 226. 翻转二叉树
给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。
示例 1:
text
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]
示例 2:
text
输入:root = [2,1,3] 输出:[2,3,1]
示例 3:
text
输入:root = [] 输出:[]
解题思路
翻转二叉树的核心思想是:对于每个节点,交换它的左右子树,然后递归或迭代地处理所有子节点。这道题虽然简单,但考察了对二叉树遍历的理解,也是很多面试的"热身题"。
解法一:递归(DFS,前序遍历)
思路
最直观的解法。对于当前节点root:
交换它的左右子节点
递归翻转左子树
递归翻转右子树
这本质上是前序遍历的应用。
代码实现
java
class Solution { public 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; } }更简洁的写法:
java
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),n 为节点数,每个节点访问一次
空间复杂度:O(h),h 为树的高度,递归栈的深度
解法二:递归(后序遍历)
思路
也可以用后序遍历:先递归翻转左右子树,然后再交换当前节点的左右子节点。
代码实现
java
class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) return null; // 后序遍历:先处理子树 invertTree(root.left); invertTree(root.right); // 再交换当前节点的左右子节点 TreeNode temp = root.left; root.left = root.right; root.right = temp; return root; } }前序 vs 后序
| 遍历方式 | 区别 |
|---|---|
| 前序遍历 | 先交换当前节点,再处理子节点 |
| 后序遍历 | 先处理子节点,再交换当前节点 |
两者都能正确完成翻转,前序更符合"由上到下"的直觉,后序则体现了"由下到上"的思想。
解法三:迭代(BFS,层序遍历)
思路
使用队列进行层序遍历,逐层处理每个节点:将当前节点的左右子节点交换,然后将非空的子节点加入队列继续处理。
代码实现
java
import java.util.LinkedList; import java.util.Queue; class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) return null; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { TreeNode current = queue.poll(); // 交换当前节点的左右子节点 TreeNode temp = current.left; current.left = current.right; current.right = temp; // 将子节点加入队列 if (current.left != null) { queue.offer(current.left); } if (current.right != null) { queue.offer(current.right); } } return root; } }复杂度分析
时间复杂度:O(n)
空间复杂度:O(n),队列在最坏情况下存储 n/2 个节点
解法四:迭代(DFS,前序遍历)
思路
使用栈模拟递归的前序遍历过程。
代码实现
java
import java.util.Stack; class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) return null; Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode current = stack.pop(); // 交换左右子节点 TreeNode temp = current.left; current.left = current.right; current.right = temp; // 先压右再压左,确保左子树先被处理(模拟前序遍历) if (current.right != null) { stack.push(current.right); } if (current.left != null) { stack.push(current.left); } } return root; } }复杂度分析
时间复杂度:O(n)
空间复杂度:O(h),栈的深度
解法对比
| 解法 | 空间复杂度 | 优点 | 适用场景 |
|---|---|---|---|
| 递归(前序) | O(h) | 代码简洁,最直观 | 默认首选 |
| 递归(后序) | O(h) | 体现后序思想 | 学习意义 |
| BFS 迭代 | O(n) | 避免递归栈溢出 | 树很深时 |
| DFS 迭代 | O(h) | 空间优于 BFS | 树很深时 |
推荐:日常刷题用递归最简洁,面试中如果要求非递归可以用迭代版本。
经典梗:Max Howell 的故事
这道题之所以出名,很大程度是因为 2015 年 Homebrew 作者 Max Howell 在 Twitter 上的吐槽:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
大意:Google 说"我们 90% 的工程师都用你写的软件,但你连翻转二叉树都写不出来,滚蛋吧。"
这个故事让这道题成为面试领域的"传奇",也提醒我们:不要因为基础题简单就忽视它,大神也会栽跟头 😂
扩展思考
对称二叉树(LeetCode 101):翻转后的树是否等于原树?
二叉树的镜像:翻转二叉树在图形学中也有应用
N 叉树的翻转:思路类似,将每个节点的子节点列表反转
总结
翻转二叉树的本质就是交换每个节点的左右子节点。无论是递归还是迭代,核心操作都是交换。
这道题看似简单,但考察了对二叉树遍历的掌握程度,也是很多公司面试的"试金石"。熟练掌握三种解法(递归、BFS、DFS),面试中就可以游刃有余。
题目链接 & 题解链接
题目链接:LeetCode 226. 翻转二叉树
题解链接:LeetCode 官方题解 - 翻转二叉树
如果这篇文章对你有帮助,欢迎点赞、收藏、关注!更多 LeetCode HOT 100 题解持续更新中~