(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.")。
  • 掌握此题有助于理解后续更复杂的树操作(如对称树、相同树、镜像等)。
相关推荐
独隅18 分钟前
IntelliJ IDEA 接入多种AI大模型插件终极指南(2026.1 企业合规版)
java·人工智能·intellij-idea
还是奇怪1 小时前
Simon Willison 用 DSPy 优化 Datasette Agent 提示词:提示工程正在变成可测试的软件工程
java·开发语言·软件工程
zfoo-framework1 小时前
1.ansible安装 2.虚拟机克隆
java
码上解惑1 小时前
从 Dify 工作流说起:常用节点怎么选、怎样组合?
java·人工智能·ai·agent·dify·智能体·spring ai
稚南城才子,乌衣巷风流1 小时前
ST 表(Sparse Table)算法详解:原理、实现与应用
算法
hold?fish:palm2 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle2 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木2 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
不会就选b2 小时前
算法日常・每日刷题--<归并排序>1
数据结构·算法
程序员-珍2 小时前
报错下载android sdk失败
android·java