(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.")。
  • 掌握此题有助于理解后续更复杂的树操作(如对称树、相同树、镜像等)。
相关推荐
qyzm1 小时前
天梯赛练习(3月13日)
开发语言·数据结构·python·算法·贪心算法
月月玩代码1 小时前
Actuator,Spring Boot应用监控与管理端点!
java·spring boot·后端
逆境不可逃1 小时前
LeetCode 热题 100 之 64. 最小路径和 5. 最长回文子串 1143. 最长公共子序列 72. 编辑距离
算法·leetcode·动态规划
feng一样的男子2 小时前
NFS 扩展属性 (xattr) 提示操作不支持解决方案
linux·go
CoderCodingNo2 小时前
【GESP】C++五级练习题 luogu-P1182 数列分段 Section II
开发语言·c++·算法
放下华子我只抽RuiKe52 小时前
机器学习全景指南-直觉篇——基于距离的 K-近邻 (KNN) 算法
人工智能·gpt·算法·机器学习·语言模型·chatgpt·ai编程
kisshuan123962 小时前
[特殊字符]【深度学习】DA3METRIC-LARGE单目深度估计算法详解
人工智能·深度学习·算法
阿珍爱上了阿强,在一个有星星的夜晚2 小时前
node后端页面性能监测分析
java·学习方法
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章33-Blod分析
图像处理·人工智能·opencv·算法·计算机视觉
Java程序之猿2 小时前
SpringBoot + camel+IBM MQ实现消息队列处理
java·spring boot·mybatis