LeetCode 226. 翻转二叉树(Invert Binary Tree)

一、题目描述

给定一棵二叉树的根节点 root,请你翻转这棵二叉树,并返回翻转后的根节点。

所谓翻转二叉树,就是交换每个节点的左右子树。

示例:

输入:

复制代码
        4
      /   \
     2     7
    / \   / \
   1   3 6   9

输出:

复制代码
        4
      /   \
     7     2
    / \   / \
   9   6 3   1

二、为什么这题值得学习

LeetCode 226 是二叉树最经典的入门题之一,也是很多公司喜欢考察的 DFS 基础题。

虽然代码只有几行,但它能够帮助我们理解:

  • 二叉树递归思想
  • DFS(深度优先搜索)
  • 前序、后序遍历的应用
  • BFS(层序遍历)

这道题最大的价值不是交换左右节点,而是理解递归到底是在做什么


三、核心思想

翻转二叉树其实就是:

遍历整棵树,把每一个节点的左右孩子交换即可。

例如:

原树:

复制代码
      A
     / \
    B   C

交换后:

复制代码
      A
     / \
    C   B

对于每一个节点都执行同样的操作,因此天然适合递归。


四、解法一:递归(推荐)

思路

对于当前节点:

  1. 交换左右孩子;
  2. 翻转左子树;
  3. 翻转右子树。

递归结束条件:

复制代码
root == null

直接返回。


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;
    }
}

执行过程

例如:

复制代码
      4
     / \
    2   7

第一步:

交换:

复制代码
      4
     / \
    7   2

继续递归:

复制代码
翻转7

↓

翻转2

直到所有节点完成交换。


复杂度分析

指标 数值
时间复杂度 O(n)
空间复杂度 O(h)(递归栈)

其中:

  • n 为节点数量
  • h 为树高

五、解法二:DFS(显式栈)

递归其实就是系统帮我们维护了一个栈。

我们也可以自己维护一个栈。


思路

  1. 根节点入栈;
  2. 弹出节点;
  3. 交换左右孩子;
  4. 左右孩子继续入栈。

直到栈为空。


Java 实现

复制代码
class Solution {

    public 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 temp = node.left;
            node.left = node.right;
            node.right = temp;

            if (node.left != null) {
                stack.push(node.left);
            }

            if (node.right != null) {
                stack.push(node.right);
            }
        }

        return root;
    }
}

复杂度分析

指标 数值
时间复杂度 O(n)
空间复杂度 O(h)

六、解法三:BFS(层序遍历)

除了 DFS,还可以按层遍历整棵树。

利用队列:

每访问一个节点:

直接交换左右孩子。


思路

复制代码
根节点入队

↓

弹出节点

↓

交换左右孩子

↓

左右孩子入队

↓

直到队列为空

Java 实现

复制代码
class Solution {

    public TreeNode invertTree(TreeNode root) {

        if (root == null) {
            return null;
        }

        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.offer(root);

        while (!queue.isEmpty()) {

            TreeNode node = queue.poll();

            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;

            if (node.left != null) {
                queue.offer(node.left);
            }

            if (node.right != null) {
                queue.offer(node.right);
            }
        }

        return root;
    }
}

复杂度分析

指标 数值
时间复杂度 O(n)
空间复杂度 O(n)

最坏情况下,队列可能保存整层节点。


七、三种解法对比

解法 推荐程度 时间复杂度 空间复杂度 面试评价
递归 ⭐⭐⭐⭐⭐ O(n) O(h) 最常用、代码最简洁
DFS(栈) ⭐⭐⭐⭐ O(n) O(h) 展示递归转迭代能力
BFS(队列) ⭐⭐⭐⭐ O(n) O(n) 展示层序遍历思想

八、面试高频追问

❓ 为什么递归能够解决?

因为每个节点执行的操作完全一致:

交换左右子树。

每棵子树又是一棵完整的二叉树,因此天然具有递归结构。


❓ 为什么可以前序也可以后序?

因为:

交换左右孩子不会影响最终结果。

所以:

复制代码
交换

↓

递归左右

或者:

复制代码
递归左右

↓

交换

最终得到的树完全一样。


❓ 时间复杂度是多少?

每个节点只访问一次。

所以:

复制代码
O(n)

❓ 空间复杂度是多少?

递归:

复制代码
O(h)

h 为树高。

如果:

树退化成链表。

最坏:

复制代码
O(n)

九、常见错误

1. 忘记交换

很多人写成:

复制代码
invertTree(root.left);
invertTree(root.right);

结果:

没有交换。

树不会发生变化。


2. 空指针

忘记:

复制代码
if(root==null)

会:

复制代码
root.left

空指针异常。


3. 交换顺序写错

正确:

复制代码
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;

不要直接:

复制代码
root.left = root.right;
root.right = root.left;

否则:

左右孩子都会变成同一个节点。


十、一句话总结

翻转二叉树的本质就是遍历整棵树,并交换每个节点的左右子树 。递归实现最简单,也是面试最推荐的写法;DFS 和 BFS 本质上都是对递归思想的迭代实现,三种方法时间复杂度均为 O(n)

相关推荐
Asize6 小时前
146. LRU 缓存
算法
Asize6 小时前
543. 二叉树的直径
算法
lemon_sjdk6 小时前
ObjectProperty
java·开发语言·算法
Zentceh6 小时前
AI-ISP在夜视机芯中的应用:从传统ISP到PixelClean全彩夜视的进化
人工智能·科技·算法·计算机视觉·车载系统·视频·智能硬件
xier_ran7 小时前
【infra之路】AWQ 详解:激活感知权重保护,让 W4A16 量化精度超越 GPTQ
线性代数·算法·机器学习·量化·infra
亦皓ai7 小时前
AI时代后端工程(二):AI把代码写得越来越快,我却越来越不敢让它直接开工了
人工智能·算法·机器学习·搜索引擎·transformer
玖玥拾9 小时前
LeetCode 392 判断子序列
笔记·算法·leetcode
学习星球9 小时前
DSA 面试精讲 · Trie 前缀树:一文掌握字符串前缀匹配
面试·职场和发展
重生之后端学习10 小时前
239. 滑动窗口最大值[困难]✅
java·数据结构·算法·leetcode·职场和发展
fpcc10 小时前
算法和数据结构—动态规划法
数据结构·算法·动态规划