(LeetCode-Hot100)226. 翻转二叉树

❌|✅|💡|📌 问题简介

LeetCode 226. 翻转二叉树

复制代码
题解github地址: https://github.com/swf2020/LeetCode-Hot100-Solutions

题目描述

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


📌 示例说明

示例 1:

复制代码
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

复制代码
输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

复制代码
输入:root = []
输出:[]

💡 解题思路

翻转二叉树的本质是将每个节点的左右子树互换。我们可以采用以下两种主流方法:

方法一:递归(深度优先搜索 DFS)

  1. 终止条件 :如果当前节点为 null,直接返回。
  2. 交换左右子树:对当前节点,交换其左右子节点。
  3. 递归处理子树:对左子树和右子树分别进行翻转。
  4. 返回根节点

✅ 优点:代码简洁,逻辑清晰。

❌ 缺点:在极端不平衡树中可能导致栈溢出(但 LeetCode 测试用例通常不会触发)。

方法二:迭代(广度优先搜索 BFS / 层序遍历)

  1. 使用队列(或栈)存储待处理的节点。
  2. 每次从队列中取出一个节点,交换其左右子节点。
  3. 如果左/右子节点非空,则将其加入队列。
  4. 重复直到队列为空。

✅ 优点:避免递归调用栈,适用于极深树。

❌ 缺点:代码稍复杂,需额外空间维护队列。


💻 代码实现

java 复制代码
// 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;
    }

    // 方法二:迭代(BFS)
    public TreeNode invertTreeIterative(TreeNode root) {
        if (root == null) return null;
        Queue<TreeNode> queue = new LinkedList<>();
        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;
    }
}
go 复制代码
// Go 实现
package main

// Definition for a binary tree node.
type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

// 方法一:递归
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }
    // 交换左右子树
    root.Left, root.Right = root.Right, root.Left
    // 递归翻转
    invertTree(root.Left)
    invertTree(root.Right)
    return root
}

// 方法二:迭代(BFS)
func invertTreeIterative(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        node := queue[0]
        queue = queue[1:]
        // 交换
        node.Left, node.Right = node.Right, node.Left
        // 入队非空子节点
        if node.Left != nil {
            queue = append(queue, node.Left)
        }
        if node.Right != nil {
            queue = append(queue, node.Right)
        }
    }
    return root
}

🎯 示例演示

root = [4,2,7,1,3,6,9] 为例:

原始树结构:

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

翻转后:

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

每一步递归或迭代都确保当前节点的左右子树被交换,最终整棵树完成翻转。


✅ 答案有效性证明

  • 正确性 :通过数学归纳法可证。
    • 基础情况:空树或单节点树,翻转后不变,正确。
    • 归纳假设:假设对高度 ≤ h 的树翻转正确。
    • 归纳步骤:对高度 h+1 的树,先交换左右子树(均为高度 ≤ h),再递归翻转,由归纳假设成立,整体正确。
  • 边界处理:空输入返回空,符合预期。
  • LeetCode 测试:所有测试用例通过。

📊 复杂度分析

方法 时间复杂度 空间复杂度 说明
递归(DFS) O(n) O(h) h 为树高,最坏 O(n),平均 O(log n)
迭代(BFS) O(n) O(w) w 为最大层宽,最坏 O(n)(完全二叉树最后一层)

其中 n 为节点总数。


🧠 问题总结

  • 核心思想:树的翻转 = 每个节点左右子树交换。
  • 递归是最直观解法,代码简洁且易于理解。
  • 迭代适用于栈空间受限场景,但 LeetCode 中递归通常足够。
  • 此题是理解树遍历与递归的经典入门题,常被用于面试(如 Max Howell 的著名梗:"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.")。
  • 掌握此题有助于理解后续更复杂的树操作(如对称树、相同树、镜像等)。
相关推荐
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
小O的算法实验室1 天前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
于慨1 天前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
swg3213211 天前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
tyung1 天前
一个 main.go 搞定协作白板:你画一笔,全世界都看见
后端·go
gelald1 天前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川1 天前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月1 天前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming6661 天前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川1 天前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java