二叉树最小深度:递归与BFS解法详解
1. 二叉树最小深度问题解析今天我们来聊聊LeetCode上第111题二叉树的最小深度这是二叉树类题目中的经典入门题。很多人在面试时都遇到过这个题目看似简单却暗藏玄机。我第一次做这题时也踩过坑后来在实际工作中发现这类基础算法思想在解决实际问题时特别有用。最小深度是指从根节点到最近叶子节点的最短路径上的节点数量。注意是到叶子节点的距离叶子节点是指没有子节点的节点。这与最大深度二叉树的高度有本质区别很多人容易混淆这两个概念。2. 问题分析与解法思路2.1 理解题目要求首先我们需要明确几个关键点最小深度的定义是从根节点到最近叶子节点的最短路径叶子节点是指左右子节点都为空的节点空树的最小深度为0只有根节点的树最小深度为1常见误区是把最小深度简单理解为左右子树最小深度的较小值加1。这种思路在遇到单边子树时会出错比如当左子树为空时最小深度应该是右子树的最小深度加1而不是1因为此时根节点不是叶子节点。2.2 递归解法详解递归是最直观的解法代码简洁但需要理解递归终止条件def minDepth(root): if not root: return 0 if not root.left: return minDepth(root.right) 1 if not root.right: return minDepth(root.left) 1 return min(minDepth(root.left), minDepth(root.right)) 1这个解法的时间复杂度是O(n)因为每个节点只访问一次。空间复杂度在最坏情况下树退化为链表是O(n)平均情况下是O(logn)。注意递归解法要特别注意单边子树的情况这是最容易出错的地方。我在面试候选人时发现90%的错误都发生在这里。2.3 迭代解法BFS实现广度优先搜索BFS是更高效的解法因为它可以在找到第一个叶子节点时立即返回而不需要遍历整棵树from collections import deque def minDepth(root): if not root: return 0 queue deque([(root, 1)]) while queue: node, depth queue.popleft() if not node.left and not node.right: return depth if node.left: queue.append((node.left, depth 1)) if node.right: queue.append((node.right, depth 1)) return 0BFS解法的时间复杂度在最坏情况下是O(n)但平均情况下会比递归更快找到解。空间复杂度是O(n)因为需要存储节点队列。3. 算法优化与变种问题3.1 性能对比与选择递归和迭代两种解法各有优劣递归代码简洁但可能有栈溢出风险极深树BFS更高效适合求最小深度这类最近问题DFS深度优先搜索也可以解但不如BFS直观在实际应用中如果树比较平衡递归解法足够如果树可能很深或偏向一侧BFS更可靠。我在工作中处理大型目录结构时就选择了BFS方案。3.2 常见变种问题基于最小深度问题LeetCode上还有几个变种值得关注最大深度LeetCode 104题平衡二叉树判断LeetCode 110题路径总和问题LeetCode 112题二叉树的所有路径LeetCode 257题这些题目都可以用类似的递归或BFS思路解决建议一起练习。4. 实际应用场景4.1 文件系统最短路径二叉树最小深度算法可以应用于查找文件系统中最短路径。比如我们需要找到一个目录下离根目录最近的空文件夹import os from collections import deque def find_nearest_empty_dir(root_dir): queue deque([(root_dir, 0)]) while queue: current_dir, depth queue.popleft() if not os.listdir(current_dir): return depth for entry in os.listdir(current_dir): path os.path.join(current_dir, entry) if os.path.isdir(path): queue.append((path, depth 1)) return -14.2 网络爬虫策略优化在网络爬虫设计中我们可以用类似算法确定从首页到目标页面的最短点击距离。这有助于优化爬取策略和优先级。5. 常见错误与调试技巧5.1 典型错误案例忽略单边子树情况# 错误解法 def minDepth(root): if not root: return 0 return min(minDepth(root.left), minDepth(root.right)) 1这个解法在输入为[1,2]时会错误返回1而正确答案是2。混淆深度定义把根节点深度算作0还是1要统一LeetCode通常按1开始计数。5.2 调试技巧使用小型测试用例验证边界条件空树 []只有根节点 [1]左斜树 [1,2,null,3]右斜树 [1,null,2,null,3]完全二叉树 [1,2,3,4,5,6]打印递归过程或BFS队列状态观察算法执行流程。6. 进阶思考与扩展6.1 多叉树的最小深度对于多叉树每个节点可能有多个子节点算法思路相同只需调整子节点遍历方式def minDepth(root): if not root: return 0 if not root.children: return 1 return min(minDepth(child) for child in root.children) 16.2 带权重的最小深度问题如果每条边有不同的权重问题就变成了求带权最短路径可以用Dijkstra算法解决。这在网络路由、地图导航等场景很常见。7. 算法复杂度分析让我们详细分析一下递归和BFS两种解法的时间和空间复杂度递归解法时间复杂度O(n)每个节点访问一次空间复杂度最坏O(n)树退化为链表时递归深度为n平均O(logn)BFS解法时间复杂度O(n)最坏情况访问所有节点空间复杂度O(n)队列最多存储n个节点实际测试表明在随机生成的平衡二叉树上BFS通常比递归快20-30%因为可以提前终止。8. 不同语言实现对比8.1 Java实现// BFS解法 public int minDepth(TreeNode root) { if (root null) return 0; QueueTreeNode queue new LinkedList(); queue.offer(root); int depth 1; while (!queue.isEmpty()) { int size queue.size(); for (int i 0; i size; i) { TreeNode node queue.poll(); if (node.left null node.right null) { return depth; } if (node.left ! null) queue.offer(node.left); if (node.right ! null) queue.offer(node.right); } depth; } return depth; }8.2 C实现// 递归解法 int minDepth(TreeNode* root) { if (!root) return 0; if (!root-left) return minDepth(root-right) 1; if (!root-right) return minDepth(root-left) 1; return min(minDepth(root-left), minDepth(root-right)) 1; }不同语言的实现思路相同主要区别在语法和数据结构的使用上。Java通常使用Queue接口C可以直接使用STL的queue。9. 单元测试与验证编写全面的测试用例是确保算法正确性的关键import unittest class TestMinDepth(unittest.TestCase): def test_empty_tree(self): self.assertEqual(minDepth(None), 0) def test_single_node(self): root TreeNode(1) self.assertEqual(minDepth(root), 1) def test_skewed_tree(self): root TreeNode(1) root.left TreeNode(2) root.left.left TreeNode(3) self.assertEqual(minDepth(root), 3) def test_balanced_tree(self): root TreeNode(1) root.left TreeNode(2) root.right TreeNode(3) root.left.left TreeNode(4) self.assertEqual(minDepth(root), 2)10. 实际工程中的应用思考在实际工程中我们很少直接使用这种基础算法但它的思想无处不在。比如在UI渲染树中确定最短更新路径在游戏AI中寻找最短行动序列在社交网络中计算最短关系链在组织架构中查找最近的共同上级理解这些基础算法能帮助我们更好地设计系统架构和解决复杂问题。我在开发一个文件同步工具时就用类似的思路优化了冲突检测的效率。

相关新闻

基于Claude Code的多Agent路由与定义机制:从单体到协作的架构实践

基于Claude Code的多Agent路由与定义机制:从单体到协作的架构实践

1. 项目概述:从单体Agent到多Agent协作的跃迁最近在折腾一个基于Claude Code的AI项目,核心目标是把一个“聪明但孤独”的单体Agent,升级成一个能分工协作、高效运转的“多Agent团队”。这个想法源于一个很实际的痛点:面对一个复杂…

2026/10/13 22:03:00 阅读更多 →
Windows 10下Maven环境配置全攻略:从JDK到镜像优化

Windows 10下Maven环境配置全攻略:从JDK到镜像优化

1. 项目概述与环境准备最近在帮几个刚入行的朋友配置开发环境,发现很多人卡在了Maven的配置上。明明照着网上教程一步步来,最后mvn -v命令还是报错,要么是JAVA_HOME找不到,要么是命令不识别,折腾半天心态都崩了。其实&…

2026/10/13 22:02:15 阅读更多 →
SonarQube从零到一:Docker部署、核心配置与代码质量门禁实战

SonarQube从零到一:Docker部署、核心配置与代码质量门禁实战

1. 项目概述:为什么我们需要SonarQube?在代码的世界里,我们常常会遇到这样的场景:一个项目初期跑得飞快,但随着时间推移,新功能越加越多,代码库越来越臃肿,维护成本呈指数级上升。你…

2026/9/28 15:16:02 阅读更多 →

最新新闻

Python Plotly交互式数据可视化:从快速出图到精细定制

Python Plotly交互式数据可视化:从快速出图到精细定制

做数据分析的同学都有一个共同感受:数据算完之后,最头疼的不是处理逻辑,而是怎么把结果变成一张别人一眼能看懂的图。这两年我用得最顺手的工具就是 Plotly,一个典型的 Python 交互式绘图库。用 Plotly 创建交互式图表&#xff0c…

2026/10/13 22:03:47 阅读更多 →
基于Spring Boot和Vue的电影订票管理系统全栈项目

基于Spring Boot和Vue的电影订票管理系统全栈项目

每年做课程设计或者毕业设计的季节,总有人问我"有没有一个既能体现技术栈又不算太复杂、最好还带完整界面的项目"。老实说,这类需求里出镜率最高的就是各种"管理系统",而其中电影订票管理系统又是一直没凉过的经典选题。…

2026/10/13 22:03:47 阅读更多 →
机器学习集成学习实战:三大流派与工程应用

机器学习集成学习实战:三大流派与工程应用

集成学习这几年在机器学习面试和实际工程里都是绕不开的东西。不管你是刚开始学模型,还是已经在跑实验,迟早会遇到一个问题:单个模型的效果到了瓶颈,怎么再往上提一点?很多人第一反应是换更复杂的模型,但更…

2026/10/13 22:03:47 阅读更多 →
WEKA数据挖掘入门:从ARFF格式到J48决策树与交叉验证实战

WEKA数据挖掘入门:从ARFF格式到J48决策树与交叉验证实战

简介:一份面向数据挖掘初学者与课程学习者的WEKA中文详细教程PPT,围绕怀卡托智能分析环境(WEKA)的开源特性、获得ACM SIGKDD奖项的里程碑地位及常见应用场景展开,适合作为高校数据挖掘、机器学习课程的配套讲义或自学入…

2026/10/13 22:03:47 阅读更多 →
支付系统设计与落地:状态机、幂等、对账与避坑指南

支付系统设计与落地:状态机、幂等、对账与避坑指南

线下业务上线支付系统的那段时间,几乎每天都要和数据、异常单、渠道对账单较劲。当时踩过的坑、重构过的状态机、跟渠道商务来回确认的限额规则,后来都沉淀成了这套经验。今天不聊架构图,也不念文档,就实打实拆一下“支付系统”从…

2026/10/13 22:03:47 阅读更多 →
同花顺日线文件解析:从二进制乱码到可回测的OHLCV表

同花顺日线文件解析:从二进制乱码到可回测的OHLCV表

简介:这份资源面向金融数据分析初学者与量化爱好者,聚焦同花顺日线二进制文件(.day)的解析问题。压缩包仅4KB,内含2个文件:一个以600000为代码的日线样本文件,以及一份约20行的Python解析脚本&a…

2026/10/13 22:02:46 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →