二叉树的最小深度——递归法、迭代法
1题目
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5
2链接
题目:111. 二叉树的最小深度 - 力扣(Leetcode)
视频:看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度_哔哩哔哩_bilibili
3解题思路
本题前序遍历和后序遍历都可以,前序求的是深度,后序求的是高度。
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)
那么使用后序遍历,其实求的是根节点到叶子节点的最小距离,就是求高度的过程,不过这个最小距离 也同样是最小深度。
以下讲解中遍历顺序上依然采用后序遍历(因为要比较递归返回之后的结果,本文我也给出前序遍历的写法)。
本题还有一个误区,在处理节点的过程中,最大深度很容易理解,最小深度就不那么好理解,如图:

这就重新审题了,题目中说的是:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。
什么是叶子节点,左右孩子都为空的节点才是叶子节点!
3.1递归法
递归三部曲:
确定递归函数的参数和返回值
参数为要传入的二叉树根节点,返回的是int类型的深度。
代码如下:
int getDepth(TreeNode* node)
确定终止条件
终止条件也是遇到空节点返回0,表示当前节点的高度为0。
代码如下:
if (node == NULL) return 0;
确定单层递归的逻辑
这块和求最大深度可就不一样了,一些同学可能会写如下代码:
int leftDepth = getDepth(node->left);
int rightDepth = getDepth(node->right);
int result = 1 + min(leftDepth, rightDepth);
return result;
这个代码就犯了此图中的误区:

如果这么求的话,没有左孩子的分支会算为最短深度。
所以,如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
3.2迭代法
层序遍历
需要注意的是,只有当左右孩子都为空的时候,才说明遍历到最低点了。如果其中一个孩子不为空则不是最低点
4代码
4.1递归法——后序遍历
//递归法——后序遍历
class Solution {
public:int getDepth(TreeNode* root) {// 如果节点为空,深度为0if (root == nullptr) {return 0;}// 递归计算左子树的深度和右子树的深度int leftDepth = getDepth(root->left);//左int rightDepth = getDepth(root->right);//右 //后续为中// 如果当前节点左子树为空且右子树不为空,则最小深度为1加右子树的最小深度if (root->left == nullptr && root->right != nullptr) {return 1 + rightDepth;}// 如果当前节点右子树为空且左子树不为空,则最小深度为1加左子树的最小深度if (root->left != nullptr && root->right == nullptr) {return 1 + leftDepth;}// 否则,取其左右子树最小深度的较小值,并加上1作为当前节点的深度,即可得到整棵树的最小深度int result = min(leftDepth, rightDepth) + 1;return result;}int minDepth(TreeNode* root) {// 调用getDepth函数来获取root节点的最小深度,并返回计算结果return getDepth(root);}
};
这段 C++ 代码中定义了一个名为 Solution 的类,其中实现了两个方法:
getDepth 函数,递归计算当前节点的深度。如果该节点左子树为空但右子树不为空,则最小深度为1加右子树的最小深度;如果该节点右子树为空但左子树不为空,则最小深度为1加左子树的最小深度;否则,返回左右子树最小深度的较小值,并加上1作为当前节点的深度,即可得到整棵树的最小深度。
minDepth 函数,调用 getDepth 函数并返回计算结果。
4.2递归法——AI生成
//递归法——后序遍历——from AI
// 时间复杂度:O(n),其中n是二叉树的节点个数。每个节点最多被访问一次,因此时间复杂度是O(n)。
// 空间复杂度:O(h),其中h是二叉树的高度。最坏情况下,二叉树呈现链状,空间复杂度是O(n);平均情况下,空间复杂度是O(logn)。
class Solution {
public:int minDepth(TreeNode* root) {if (!root) { // 如果根节点为空,返回0return 0;}if (!root->left && !root->right) { // 如果根节点左右子树都为空,返回1return 1;}int left_depth = INT_MAX; // 记录左子树最小深度if (root->left) {left_depth = minDepth(root->left); // 递归求左子树最小深度}int right_depth = INT_MAX; // 记录右子树最小深度if (root->right) {right_depth = minDepth(root->right); // 递归求右子树最小深度}return min(left_depth, right_depth) + 1; // 返回左右子树最小深度加1的最小值}
};
该函数的输入参数为二叉树的根节点 root,返回值为二叉树的最小深度。首先判断根节点是否为空,如果为空,直接返回深度为0;如果根节点的左右子树都为空,说明当前节点为叶子节点,返回深度为1。
然后,定义变量 left_depth 和 right_depth 分别记录左右子树的最小深度。如果当前节点有左子树,递归调用 minDepth 函数计算左子树的最小深度;同样的,如果当前节点有右子树,则递归计算右子树的最小深度。然后,返回左右子树最小深度加1的最小值。
这个递归算法的思路是:每次从根节点开始,递归计算左右子树的最小深度,然后返回左右子树最小深度加1的最小值,即为整棵树的最小深度。
4.3迭代法
//迭代法——层序遍历
class Solution{
public:int minDepth(TreeNode* root) {// 如果节点为空,返回深度为0if (root == nullptr) return 0;// 创建一个队列,将根节点加入队列中,初始深度为0queue<TreeNode*> que;que.push(root);int depth = 0;// 循环遍历队列中的每个节点,直到队列为空while (!que.empty()) {// 记录当前队列的大小,该大小等于当前层节点的数目int size = que.size();// 每次遍历队列中的所有节点时,深度加1depth++;// 遍历当前层的所有节点,将下一层的节点加入队列中for (int i = 0; i < size; i++) {// 取出队首节点TreeNode* node = que.front();que.pop();// 将左右子节点加入队列中if (node->left) que.push(node->left);if (node->right) que.push(node->right);// 如果该节点同时没有左右子节点,返回当前深度if (!node->left && !node->right) return depth;}}// 如果整棵树根节点为0,返回深度为0return depth;}
};
这段代码定义了一个名为 Solution 的类,其中实现了一个 minDepth 函数,该函数用于计算一棵二叉树的最小深度。
该函数的输入参数为二叉树的根节点 root,返回值为二叉树的最小深度。如果 root 节点为空,直接返回深度为0。否则,创建一个队列 que,将 root 节点加入队列中,并初始化深度为0。
然后,执行一个循环,每次循环遍历队列中的所有节点,直到队列为空。在循环内,首先记录当前队列的大小 size,该大小等于当前层节点的数目;然后,将深度 depth 加1,表示进入了下一层;遍历当前层的所有节点,将每个节点的左右子节点加入队列中;如果该节点同时没有左右子节点,说明已经到达最小深度,返回当前深度。
如果循环结束后仍然没有找到任何叶子节点,则整棵树只有根节点,返回深度为1。
相关文章:

二叉树的最小深度——递归法、迭代法
1题目给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。示例 1:输入:root [3,9,20,null,null,15,7]输出:2示例 2:输入&…...
Vue中常使用的三种刷新页面的方式
一、通过js原始方法刷新 缺点: 出现闪白 目录 一、通过js原始方法刷新 二、通过Vue自带的路由进行跳转 三、通过在APP页面进行demo进行刷新(推荐) 1.vue2写法 2. vue3.2写法 <template><div><div class"header"><button clic…...

【Shell】脚本
Shell脚本脚本格式第一个Shell脚本:hello.sh脚本常用执行方式1. bash或sh脚本的相对路径或绝对路径2. 输入脚本的绝对路径或相对路径3. 在脚本的路径前加上.或者source脚本格式 脚本以#!/bin/bash开头(指定解析器) #! 是一个约定的标记&…...
Mybatis的多表操作
1.Mybatis多表查询 1.1一对一查询 1.一对一查询的模型 用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户 一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户2.创建Order和User实体public class…...
【JVM】字节码指令全解
文章目录 入门案例原始 java 代码编译后的字节码文件常量池载入运行时常量池方法字节码载入方法区main 线程开始运行,分配栈帧内存执行引擎开始执行字节码bipush 10istore_1ldc #3istore_2iload_1iload_2iaddistore_3getstatic #4iload_3invokevirtual #5return条件判断指令循…...

【精品】华为认证数通HCIA+HCIP题库分享(含答案解析)
嗨~大家好久不见,我是薄荷学姐,随着华为业务也全球领域的迅猛发展,越来越多人开始重视华为认证的重要性。今天给大家分享一下去年8月份的题库,基本都是一样,希望可以帮助到大家哈想要通过华为认证,除了进行…...
Qt cmake 资源文件的加载
Qt cmake 资源文件的加载概述qt_add_resourcesqt5_add_resourcesqt6_add_resources是否需要加载qrc文件需要加载qrc的情况不需要加载qrc的情况C 代码加载示例加载PNG加载CSS文件加载qrc文件Qt6相对于Qt5的一些变化Qt6和Qt5在加载资源文件方面的区别主要集中在两个方面ÿ…...

【链表OJ题(九)】环形链表延伸问题以及相关OJ题
环形链表OJ题 1. 环形链表 链接:141. 环形链表 描述: 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环&…...

【C++初阶】四、类和对象(下)
文章目录一、再谈构造函数构造函数体赋值初始化列表explicit关键字二、Static成员引入- 计算类中创建了多少个类对象概念特性静态成员函数的访问三、友元友元函数友元类四、内部类五、匿名对象六、拷贝对象时的一些编译器优化一、再谈构造函数 构造函数体赋值 在创建对象时&a…...

IDEA maven没有Import Maven projects automatically解决办法
去年装了个 IDEA2022版本 配置maven时我才发现是个大坑 他没有import Maven projects automatically配置项 当时看到我人都麻了 然后项目呢 用了依赖 这东西还不会自动下依赖 整的我那是相当难受 还在最后还是找到了解决办法 我们在配置文件上点击右键 然后鼠标选择如下图选项…...

Java实习生------MySQL10道面试题打卡
今日语录:“没有执行力,就没有竞争力 ”🌹 参考资料:图解MySQL、MySQL面试题 1、事务有哪些特性? 原子性: 一个事务中的所有操作,要么全部完成,要么全部不完成,不会出现…...
帆软报表设计器 数据集之数据库查询
当点击数据库查询时,调用TableDataTreePane的 public void actionPerformed(ActionEvent var1) {TableDataTreePane.this.dgEdit(this.getTableDataInstance().creatTableDataPane(), TableDataTreePane.this.createDsName(this.getNamePrefix()), false);} 然后调用TableDat…...
CSDN 第三十七期竞赛题解
很少有时间来玩玩题目,上一次因为环境极为嘈杂的原因在时间上没有进入前十,挺遗憾的。 在 CSDN 参加的第一次没出锅的比赛。 大概只有最后一题值得好好讲讲。 T1:幼稚班作业 幼稚园终于又有新的作业了。 老师安排同学用发给同学的4根木棒拼接…...
Vue实战【常用的Vue小魔法】
目录🌟前言🌟能让你首次加载更快的路由懒加载,怎么能忘?🌟你是否还记得有一个叫Object.freeze的方法?🌟异步组件那么强,你是不是没用过?🌟你是不是还在comput…...
用C跑爬虫
爬虫自指定的URL地址开始下载网络资源,直到该地址和所有子地址的指定资源都下载完毕为止。 下面开始逐步分析爬虫的实现。 待下载集合与已下载集合 为了保存需要下载的URL,同时防止重复下载,我们需要分别用了两个集合来存放将要下载的URL和…...

【C语言】你真的了解结构体吗
引言✨我们知道C语言中存在着整形(int、short...),字符型(char),浮点型(float、double)等等内置类型,但是有时候,这些内置类型并不能解决我们的需求,因为我们无法用这些单一的内置类型来描述一些复杂的对象,…...

血氧仪是如何得出血氧饱和度值的?
目录 一、血氧饱和度概念 二、血氧饱和度监测意义 三、血氧饱和度的监测方式 四、容积脉搏波计算血氧饱和度原理 五、容积脉搏波波形的测量电路方案 1)光源和光电探测器的集成测量模块:SFH7050—反射式 2)模拟前端 六、市面上血氧仪类型…...
Java全栈知识(3)接口和抽象类
1、抽象类 抽象类就是由abstract修饰的类,其中没有只声明没有实现的方法就是抽象方法,抽象类中可以有0个或者多个抽象方法。 1.1、抽象类的语法 抽象类不能被final修饰 因为抽象类是一种类似于工程中未完成的中间件。需要有子类进行继承完善其功能,所…...
JavaScript == === Object.is()
文章目录JavaScript & & Object.is() 相等运算符 全等运算符Object.is() 值比较JavaScript & & Object.is() 相等运算符 相等运算符,会先进行类型转换,将2个操作数转为相同的类型,再比较2个值。 console.log("10&…...

GPT4论文翻译 by GPT4 and Human
GPT-4技术报告解读 文章目录GPT-4技术报告解读前言:摘要1 引言2 技术报告的范围和局限性3 可预测的扩展性3.1 损失预测3.2 人类评估能力的扩展4 能力评估4.1 视觉输入 !!!5 限制6 风险与缓解:7 结论前言: 这篇报告内容太多了!&am…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...