【LeetCode 热题100】深入理解二叉树结构变化与路径特性(力扣104 / 226 / 114 / 543)(Go语言版)

简介: 本博客深入探讨二叉树的深度计算、结构变换与路径分析,涵盖四道经典题目:104(最大深度)、226(翻转二叉树)、114(展开为链表)和543(二叉树直径)。通过递归与遍历策略(前序、后序等),解析每题的核心思路与实现方法。结合代码示例(Go语言),帮助读者掌握二叉树相关算法的精髓。下一讲将聚焦二叉树构造问题,欢迎持续关注!

🌲 深入理解二叉树结构变化与路径特性(力扣104 / 226 / 114 / 543)

在解题过程中,我们不仅要掌握二叉树的遍历方法,还需要理解它的结构特性。本篇博客将围绕二叉树的 深度计算、结构变换与路径分析 展开,涉及以下四道高频题:

  • [x] 104. 二叉树的最大深度
  • [x] 226. 翻转二叉树
  • [x] 114. 二叉树展开为链表
  • [x] 543. 二叉树的直径

📌 104. 二叉树的最大深度

✅ 题目描述:

给定一棵二叉树,找出其最大深度。最大深度是从根节点到最远叶子节点的最长路径上的节点数。

💡 解题思路:

这是一道非常经典的递归题。最大深度 = 左子树最大深度 与 右子树最大深度中的较大者 + 1。

我们可以使用 后序遍历(DFS),从叶子节点向上递归:

🧠 步骤解析:

  1. 递归终止条件:节点为空,返回0。
  2. 分别递归计算左右子树的最大深度。
  3. 当前节点的最大深度 = max(左,右) + 1。

💻 Go 实现:

func maxDepth(root *TreeNode) int {
   
    if root == nil {
   
        return 0
    }
    left := maxDepth(root.Left)
    right := maxDepth(root.Right)
    return max(left, right) + 1
}
AI 代码解读

📌 226. 翻转二叉树

✅ 题目描述:

翻转一棵二叉树,即左右子树交换。

示例:

输入:     4
         / \
        2   7
       / \ / \
      1  3 6  9
输出:     4
         / \
        7   2
       / \ / \
      9  6 3  1
AI 代码解读

💡 解题思路:

本质是递归地交换左右子树,可以用前序遍历来交换每个节点的左右子树。

🧠 步骤解析:

  1. 如果当前节点为 nil,返回 nil。
  2. 递归翻转左右子树。
  3. 交换左右子树。

💻 Go 实现:

func invertTree(root *TreeNode) *TreeNode {
   
    if root == nil {
   
        return nil
    }
    root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
    return root
}
AI 代码解读

📌 114. 二叉树展开为链表

✅ 题目描述:

将二叉树原地展开为一个单链表,使用前序遍历顺序,即所有右指针指向下一个节点,左指针置空。

💡 解题思路:

需要在原地修改树结构,我们可以借助 后序遍历 反向处理。

  • 倒着处理每个节点,将右子树先展开,再左子树展开,然后将当前节点的右指针指向上一个访问节点(类似于链表的前插操作)。

🧠 步骤解析(后序遍历 + 记录上一个节点):

  1. 先递归右子树,再递归左子树。
  2. 每次处理当前节点时,将其右指针指向前一个访问的节点(pre),左指针置空。
  3. 更新 pre 为当前节点。

💻 Go 实现:

var prev *TreeNode

func flatten(root *TreeNode) {
   
    if root == nil {
   
        return
    }
    flatten(root.Right)
    flatten(root.Left)
    root.Right = prev
    root.Left = nil
    prev = root
}
AI 代码解读

📌 543. 二叉树的直径

✅ 题目描述:

给定一棵二叉树,计算它的直径。直径是任意两个节点之间的最长路径,路径长度是节点数之差。

💡 解题思路:

路径可能穿过某个节点的左右子树,因此我们可以在计算深度时顺便计算当前节点左右深度之和,并维护最大值。

🧠 步骤解析(递归 + 回溯):

  1. 定义一个全局变量 res,记录最长路径。
  2. 在递归函数中,分别计算左右子树深度。
  3. 更新 res = max(res, left + right)
  4. 每次返回左右子树中最大深度 + 1。

💻 Go 实现:

var res int

func diameterOfBinaryTree(root *TreeNode) int {
   
    res = 0
    dfs(root)
    return res
}

func dfs(root *TreeNode) int {
   
    if root == nil {
   
        return 0
    }
    left := dfs(root.Left)
    right := dfs(root.Right)
    res = max(res, left+right)
    return max(left, right) + 1
}
AI 代码解读

🧠 小结与思考

题号 关键词 思维方法 特点
104 最大深度 后序遍历 求树高的典型题目
226 翻转结构 前序递归 每层交换左右子树
114 展开链表 后序遍历 倒序拼接前序路径
543 最大路径 递归+回溯 求路径最大值

📌 总结

  • 熟练掌握递归遍历策略(前序、中序、后序),在结构变化题中尤为重要。
  • 遇到路径相关问题时,可结合深度计算回溯策略
  • 在链表化或结构修改题目中,注意是否需要原地修改、是否可以使用辅助变量。

✍️ 下一篇我们将讨论“二叉树的构造”相关问题(105 & 108),包括如何根据前序中序构造树,以及如何构造平衡 BST。敬请期待!

如果这篇文章对你有帮助,欢迎点赞 👍、收藏 ⭐、关注 💻!持续更新 LeetCode 高频题详解 🚀🌲

目录
打赏
0
10
10
2
163
分享
相关文章
|
1月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
84 1
|
1月前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
52 0
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
84 1
|
1月前
|
【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)
本文深入解析了LeetCode上的两道经典回溯算法题:**22. 括号生成**与**39. 组合总和**。括号生成通过维护左右括号数量,确保路径合法并构造有效组合;组合总和则允许元素重复选择,利用剪枝优化搜索空间以找到所有满足目标和的组合。两者均需明确路径、选择列表及结束条件,同时合理运用剪枝策略提升效率。文章附有Go语言实现代码,助你掌握回溯算法的核心思想。
72 0
|
2月前
|
Go
【LeetCode 热题100】155:最小栈(详细解析)(Go语言版)
本文详细解析了力扣热题155:最小栈的解题思路与实现方法。题目要求设计一个支持 push、核心思路是使用辅助栈法,通过两个栈(主栈和辅助栈)来维护当前栈中的最小值。具体操作包括:push 时同步更新辅助栈,pop 时检查是否需要弹出辅助栈的栈顶,getMin 时直接返回辅助栈的栈顶。文章还提供了 Go 语言的实现代码,并对复杂度进行了分析。此外,还介绍了单栈 + 差值记录法的进阶思路,并总结了常见易错点,如 pop 操作时忘记同步弹出辅助栈等。
94 6
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
227 14
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。
Go语言Web开发框架实践:使用 Gin 快速构建 Web 服务
Gin 是一个高效、轻量级的 Go 语言 Web 框架,支持中间件机制,非常适合开发 RESTful API。本文从安装到进阶技巧全面解析 Gin 的使用:快速入门示例(Hello Gin)、定义 RESTful 用户服务(增删改查接口实现),以及推荐实践如参数校验、中间件和路由分组等。通过对比标准库 `net/http`,Gin 提供更简洁灵活的开发体验。此外,还推荐了 GORM、Viper、Zap 等配合使用的工具库,助力高效开发。

热门文章

最新文章

AI助理
登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问

你好,我是AI助理

可以解答问题、推荐解决方案等