创作

完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>

3天内不再提示

二叉树的最小深度

算法与数据结构 来源:代码随想录 作者:代码随想录 2022-04-28 16:27 次阅读

和求最大深度一个套路?

111.二叉树的最小深度

题目地址:https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

示例:

给定二叉树[3,9,20,null,null,15,7],

27d8a3d6-c6a8-11ec-bce3-dac502259ad0.png

返回它的最小深度 2.

思路

看完了这篇104.二叉树的最大深度,再来看看如何求最小深度。

直觉上好像和求最大深度差不多,其实还是差不少的。

遍历顺序上依然是后序遍历(因为要比较递归返回之后的结果),但在处理中间节点的逻辑上,最大深度很容易理解,最小深度可有一个误区,如图:

27ed27fc-c6a8-11ec-bce3-dac502259ad0.png

这就重新审题了,题目中说的是:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。,注意是叶子节点

什么是叶子节点,左右孩子都为空的节点才是叶子节点!

递归法

来来来,一起递归三部曲:

  1. 确定递归函数的参数和返回值

参数为要传入的二叉树根节点,返回的是int类型的深度。

代码如下:

intgetDepth(TreeNode*node)
  1. 确定终止条件

终止条件也是遇到空节点返回0,表示当前节点的高度为0。

代码如下:

if(node==NULL)return0;
  1. 确定单层递归的逻辑

这块和求最大深度可就不一样了,一些同学可能会写如下代码:

intleftDepth=getDepth(node->left);
intrightDepth=getDepth(node->right);
intresult=1+min(leftDepth,rightDepth);
returnresult;

这个代码就犯了此图中的误区:

27ed27fc-c6a8-11ec-bce3-dac502259ad0.png

如果这么求的话,没有左孩子的分支会算为最短深度。

所以,如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。

反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。

代码如下:

intleftDepth=getDepth(node->left);//左
intrightDepth=getDepth(node->right);//右
//中
//当一个左子树为空,右不为空,这时并不是最低点
if(node->left==NULL&&node->right!=NULL){
return1+rightDepth;
}
//当一个右子树为空,左不为空,这时并不是最低点
if(node->left!=NULL&&node->right==NULL){
return1+leftDepth;
}
intresult=1+min(leftDepth,rightDepth);
returnresult;

遍历的顺序为后序(左右中),可以看出:求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。

整体递归代码如下:

classSolution{
public:
intgetDepth(TreeNode*node){
if(node==NULL)return0;
intleftDepth=getDepth(node->left);//左
intrightDepth=getDepth(node->right);//右
//中
//当一个左子树为空,右不为空,这时并不是最低点
if(node->left==NULL&&node->right!=NULL){
return1+rightDepth;
}
//当一个右子树为空,左不为空,这时并不是最低点
if(node->left!=NULL&&node->right==NULL){
return1+leftDepth;
}
intresult=1+min(leftDepth,rightDepth);
returnresult;
}

intminDepth(TreeNode*root){
returngetDepth(root);
}
};

精简之后代码如下:

classSolution{
public:
intminDepth(TreeNode*root){
if(root==NULL)return0;
if(root->left==NULL&&root->right!=NULL){
return1+minDepth(root->right);
}
if(root->left!=NULL&&root->right==NULL){
return1+minDepth(root->left);
}
return1+min(minDepth(root->left),minDepth(root->right));
}
};

精简之后的代码根本看不出是哪种遍历方式,所以依然还要强调一波:如果对二叉树的操作还不熟练,尽量不要直接照着精简代码来学。

迭代法

相对于104.二叉树的最大深度,本题还可以使用层序遍历的方式来解决,思路是一样的。

如果对层序遍历还不清楚的话,可以看这篇:二叉树:层序遍历登场!

需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点

代码如下:(详细注释)

classSolution{
public:

intminDepth(TreeNode*root){
if(root==NULL)return0;
intdepth=0;
queueque;
que.push(root);
while(!que.empty()){
intsize=que.size();
depth++;//记录最小深度
for(inti=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){//当左右孩子都为空的时候,说明是最低点的一层了,退出
returndepth;
}
}
}
returndepth;
}
};

其他语言版本

Java

classSolution{
/**
*递归法,相比求MaxDepth要复杂点
*因为最小深度是从根节点到最近**叶子节点**的最短路径上的节点数量
*/
publicintminDepth(TreeNoderoot){
if(root==null){
return0;
}
intleftDepth=minDepth(root.left);
intrightDepth=minDepth(root.right);
if(root.left==null){
returnrightDepth+1;
}
if(root.right==null){
returnleftDepth+1;
}
//左右结点都不为null
returnMath.min(leftDepth,rightDepth)+1;
}
}
classSolution{
/**
*迭代法,层序遍历
*/
publicintminDepth(TreeNoderoot){
if(root==null){
return0;
}
Dequedeque=newLinkedList<>();
deque.offer(root);
intdepth=0;
while(!deque.isEmpty()){
intsize=deque.size();
depth++;
for(inti=0;i< size; i++) {
                TreeNode poll = deque.poll();
                if(poll.left==null&&poll.right==null){
//是叶子结点,直接返回depth,因为从上往下遍历,所以该值就是最小值
returndepth;
}
if(poll.left!=null){
deque.offer(poll.left);
}
if(poll.right!=null){
deque.offer(poll.right);
}
}
}
returndepth;
}
}

Python

递归法:

classSolution:
defminDepth(self,root:TreeNode)->int:
ifnotroot:
return0
ifnotroot.leftandnotroot.right:
return1

min_depth=10**9
ifroot.left:
min_depth=min(self.minDepth(root.left),min_depth)#获得左子树的最小高度
ifroot.right:
min_depth=min(self.minDepth(root.right),min_depth)#获得右子树的最小高度
returnmin_depth+1

迭代法:

classSolution:
defminDepth(self,root:TreeNode)->int:
ifnotroot:
return0
que=deque()
que.append(root)
res=1

whileque:
for_inrange(len(que)):
node=que.popleft()
#当左右孩子都为空的时候,说明是最低点的一层了,退出
ifnotnode.leftandnotnode.right:
returnres
ifnode.leftisnotNone:
que.append(node.left)
ifnode.rightisnotNone:
que.append(node.right)
res+=1
returnres
--- EOF ---

审核编辑 :李倩


  • 节点
    +关注

    关注

    0

    文章

    143

    浏览量

    22468
  • 函数
    +关注

    关注

    3

    文章

    1919

    浏览量

    56287
  • 二叉树
    +关注

    关注

    0

    文章

    43

    浏览量

    11074
收藏 人收藏

    评论

    相关推荐

    Hash哈希竞猜游戏开发方案(逻辑分析)说明

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的, 哈希系统 竞猜模式就是把任意长度的输入(又....
    发表于 06-28 16:27 6次 阅读

    请问在ch554芯片测试程序,键盘和鼠标的例程里 i = _getkey( )无法实现是为什么?

    请问下,下面的这段函数,实现的是键盘或鼠标的模拟输入,但是我把代码烧录进去,只有大小写案件可以正常,调试,其他按键和鼠标...
    发表于 06-27 07:07 35次 阅读

    ReactiveObjC objective-C的函数响应式编程框架

    ./oschina_soft/ReactiveObjC.zip
    发表于 06-24 14:26 6次 阅读
    ReactiveObjC objective-C的函数响应式编程框架

    CH545芯片可以使用malloc函数进行内存的动态分配嘛?

    如题,请问贵公司的单片机芯片(如CH545)可以使用malloc函数进行内存的动态分配嘛?      ...
    发表于 06-24 12:46 80次 阅读

    Hash哈希竞猜游戏开发方案(技术详情)简介

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的,哈l8l希2809系2756统竞猜模式就是把....
    发表于 06-24 10:08 21次 阅读

    gft4c生成函数声明列表工具

    ./oschina_soft/gft4c.zip
    发表于 06-23 14:50 10次 阅读
    gft4c生成函数声明列表工具

    分享一下STM32CubeIDE的SWV功能

    这里有个简单的方法,直接在syscalls.c文件中,改写_write()函数的内容,代码如下所示。....
    的头像 strongerHuang 发表于 06-23 10:21 167次 阅读

    rt-thread优化系列(三)软定时器的定时漂移问题分析

    所谓软定时器,是由一个线程运行维护的定时器列表。由线程调用定时器回调函数。
    的头像 出出 发表于 06-23 09:35 1458次 阅读

    C语言的具体结构与基本数据类型

    简单来说,一个C程序就是由若干头文件和函数组成。
    的头像 STM32嵌入式开发 发表于 06-22 15:35 212次 阅读

    Java反射机制清空字符串导致业务异常分析

    JVM为了提高性能和减少内存开销,在实例化字符串常量时进行了优化。JVM在Java堆上开辟了一个字符....
    的头像 openEuler 发表于 06-22 11:17 101次 阅读

    求助,mrs下scanf是映射哪个函数是 _read() 吗?

    有没有示例函数   
    发表于 06-22 07:17 59次 阅读

    AT32 Eclipse中实现分散加载的方法

    Questions:如何在Eclipse中实现分散加载? Answer: 修改脚本链接文件可以将某些函数和数据编排到特定的区域内。 1...
    发表于 06-21 19:27 1238次 阅读
    AT32 Eclipse中实现分散加载的方法

    哈希竞猜游戏系统开发Hash算法

    哈希表就是一种以键-值(key-indexed)存储数据的结构,我们只要输入待查找的值即key,即可....
    的头像 搭建punk2558 发表于 06-21 13:45 181次 阅读

    5种前沿的点云分割网络

    整体的PointNet网络中,除了点云的感知以外,还有T-Net,即3D空间变换矩阵预测网络,这主要....
    的头像 新机器视觉 发表于 06-21 11:08 194次 阅读

    使用FLASH_ProgramHalfWord函数写0x0800ff00地址进入硬件错误中断是为什么

    具体现象为 兼容模式 1k擦除后,使用FLASH_ProgramHalfWord函数写0x0800ff00地址及以后地址进入硬件错误中断,使用快写正...
    发表于 06-20 06:10 107次 阅读

    RT-Thread记录(三、RT-Thread线程操作函数)

    讲完了RT-Thread开发环境,启动流程,启动以后当然是开始跑线程了,那么自然我们得学会如何创建线....
    的头像 矜辰所致 发表于 06-20 00:31 1797次 阅读
    RT-Thread记录(三、RT-Thread线程操作函数)

    C语言实现txt文本读取与修改

    #include #include #include int main(){FILE *fp = f....
    的头像 嵌入式应用开发 发表于 06-17 17:06 554次 阅读
    C语言实现txt文本读取与修改

    C语言怎么跳出while函数

    在C语言中while函数是经常用到的,这里说一下可以跳出while函数的几种方法。
    的头像 嵌入式应用开发 发表于 06-17 15:40 231次 阅读
    C语言怎么跳出while函数

    就增量式PID的函数进行编写

    首先,就增量式PID的函数进行编写
    的头像 嵌入式应用开发 发表于 06-17 14:27 261次 阅读
    就增量式PID的函数进行编写

    栈是什么?栈有什么作用?

    大多数的处理器架构,都有实现硬件栈。有专门的栈指针寄存器,以及特定的硬件指令来完成 入栈/出栈 的操....
    的头像 一口Linux 发表于 06-17 11:19 220次 阅读

    经典的C++面试题

    这就说明:对于内建简单数据类型,delete和delete[]功能是相同的。对于自定义的复杂数据类型....
    的头像 安芯教育科技 发表于 06-17 09:10 168次 阅读

    请教各位大神,为什么我printf函数输出串口少了这三个字符(ch=)),代码图片如下

    为什么我printf函数输出串口少了这三个字符(ch=)),即输出结果为1而不是ch=1,代码图片如下...
    发表于 06-16 19:33 1042次 阅读
    请教各位大神,为什么我printf函数输出串口少了这三个字符(ch=)),代码图片如下

    LoRa节点、LoRa服务器和终端应用之间的数据传输

    通过本 LAT 实现一个从 LoRa 节点、LoRa 服务器、终端应用之间的数据或者命令的相互传输的....
    的头像 STM32单片机 发表于 06-16 16:43 429次 阅读

    RT-thread线程切换原理与实现

    RTThread官网看一下,可以发现【rt_thread_suspend】的函数说明中,特意的说明了....
    的头像 嵌入式应用开发 发表于 06-16 15:12 187次 阅读
    RT-thread线程切换原理与实现

    函数信号发生器原理图

    支持方波,正弦波切换
    发表于 06-16 14:53 9次 阅读

    J语言阵列编程语言

    ./oschina_soft/jsource.zip
    发表于 06-16 09:51 5次 阅读
    J语言阵列编程语言

    SystemVerilog包的简介与使用

    最初的Verilog语言没有一个可用于多个模块的定义。每个模块都必须有任务、函数、常量和其他共享定义....
    的头像 OpenFPGA 发表于 06-15 09:18 209次 阅读

    Goanno golang自动生成函数注释插件

    ./oschina_soft/goanno.zip
    发表于 06-14 10:18 9次 阅读
    Goanno golang自动生成函数注释插件

    软件模拟spi中ops函数有什么作用?

    发表于 06-14 09:33 676次 阅读

    哈希算法是什么,哈希游戏系统开发方案

    什么是哈希/Hash 哈希又称作“散列”,是一种数学计算机程序,它接收任何一组任意长度的输入信息,通....
    的头像 開發丨KFZ433 发表于 06-14 09:14 140次 阅读

    关于Linux Kernel非对称密码算法的实现

    baron (csdn:代码改变世界ctw),九年手机安全/SOC底层安全开发经验。擅长trustz....
    的头像 Linux阅码场 发表于 06-13 11:49 300次 阅读

    Elm函数式反应编程语言

    ./oschina_soft/compiler.zip
    发表于 06-13 10:26 11次 阅读
    Elm函数式反应编程语言

    Elixir函数式编程语言

    ./oschina_soft/elixir.zip
    发表于 06-13 09:17 20次 阅读
    Elixir函数式编程语言

    Python中pyzxing安装与测试方法

    Python中有几个开源的条码解析库,之前我测试过pyzbar、libdmx这些库,发现都是个锤子,....
    的头像 OpenCV学堂 发表于 06-12 16:50 276次 阅读

    分数阶系统参数的在线估计

    本文讨论参数识别使用调制函数方法对分数阶模型进行建模。新颖之处在于,系统不必在参数标识的开始。也就是....
    发表于 06-08 09:26 27次 阅读

    请问有无设置GPIO输入输出方向的函数?

    在逐飞开源库用的      
    发表于 06-08 06:13 73次 阅读

    哈希hash游戏竞猜开发技术逻辑—程序代码搭建

      Hash,一般翻译做“散列”,就是把任意长度的输入(又叫做预映射,pre-image),通过散列....
    发表于 06-07 10:31 45次 阅读

    Bitcoin XT Bitcoin​分支

    bitcoinxt.zip
    发表于 06-06 15:21 18次 阅读
    Bitcoin XT Bitcoin​分支

    Toshi比特币节点

    toshi.zip
    发表于 06-06 15:13 18次 阅读
    Toshi比特币节点

    如何给一个变量设置一个别名?

    在plugin.c中,提供一个函数func_init,当动态库被main dlopen之后,这个函数....
    的头像 strongerHuang 发表于 06-06 09:33 252次 阅读

    为什么C++单例模式不能直接全部使用static变量和static函数呢?

    通过getInstance()函数获取单例对象,这种模式的关键之处不是在于强迫你用函数来获取对象。关....
    的头像 Linux爱好者 发表于 06-05 14:14 216次 阅读

    console函数概述及使用方法说明

    首先,C#是一种基于net.framework框架下的一种编程语言,涉及到图像化与编程的双向使用,因....
    的头像 嵌入式应用开发 发表于 06-01 16:49 524次 阅读
    console函数概述及使用方法说明

    xiami-tools虾米工具包

    ./oschina_soft/xiami-tools.zip
    发表于 06-01 10:46 28次 阅读
    xiami-tools虾米工具包

    CH565开发加入自定义的函数异常问题如何解决?

          CH565开发加入自定义的函数,无法达到延时效果。主程序和延时函数如下。      &nb...
    发表于 06-01 07:13 182次 阅读

    详细了解队列的特点及用处

    先进先出,队列是一种操作受限的线性表,其限制条件为允许在表的一端进行插入,而在表的另一端进行删除。插....
    的头像 嵌入式应用开发 发表于 05-31 15:25 380次 阅读
    详细了解队列的特点及用处

    几种Qt种延时处理方法

    最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),....
    的头像 strongerHuang 发表于 05-31 09:30 655次 阅读

    Flask两种配置路由的方式说明

    加工中心解锁面板 Flask提供了两种方式配置路由,第一种方式是使用装饰器@app.route(ur....
    的头像 PLC工控专栏 发表于 05-31 08:43 170次 阅读
    Flask两种配置路由的方式说明

    mStopIfError这个函数的作用是什么,会导致程序卡死在这里么?

        CH565开发板中的DEMO程序,执行了get_unique_mac( local_mac );里面调用了mStopIfError函数,这个函数的...
    发表于 05-31 06:30 156次 阅读

    如何从命令行获取和解析参数

    这是一篇技术干货快文,能够快速阅读完。文章内容是关于如何从命令行获取和解析参数,包括SystemVe....
    的头像 路科验证 发表于 05-30 14:05 297次 阅读

    关于零点和极点

    假如R=1Khz,C=1uF,那么极点是s=-1000,但是我们通常说极点是1000,理由貌似是自然....
    的头像 硬件工程师炼成之路 发表于 05-30 10:46 663次 阅读

    RT-Thread全球技术大会:在RT-Thread中使用栈帧来调试程序

    百问网科技CTO韦东山,在RT-Thread全球技术大会大会中,以在RT-Thread中使用栈帧来调....
    的头像 姚小熊27 发表于 05-28 09:33 596次 阅读
    RT-Thread全球技术大会:在RT-Thread中使用栈帧来调试程序

    在IAR Embedded Workbench开发工具中如何实现堆栈保护来提高代码的安全性

    随着越来越多的嵌入式产品连接到外部网络,嵌入式产品的信息安全性(Security)越来越多地被人们关....
    的头像 21克888 发表于 05-27 15:49 2943次 阅读
    在IAR Embedded Workbench开发工具中如何实现堆栈保护来提高代码的安全性

    ATPCS基本规则

    有调用关系的所有子程序必须遵守同一种ATPCS,编译器或者汇编器在ELF格式的目标文件中设置相应的属....
    的头像 安芯教育科技 发表于 05-27 10:12 263次 阅读

    PromQL查询的整体结构及类型检查

    本文让我们一起来看看PromQL查询解析。虽然PromQL有操作符、函数、选择器等,但我们无需被本篇....
    的头像 马哥Linux运维 发表于 05-25 09:59 387次 阅读

    双向循环链表的创建

    需要注意的是,虽然双向循环链表成环状,但本质上还是双向链表,因此在双向循环链表中,依然能够找到头指针....
    的头像 C语言编程学习基地 发表于 05-24 16:27 374次 阅读

    自动控制原理的470题(第二版)

    一本自动控制原理原理的习题解,对学习自动控制原理非常有帮助!
    发表于 05-23 14:23 49次 阅读

    实际测试代码--START_TEST为例进行阐述

    在真正讲解启动过程之前,先要讲解程序下载到 Flash上的结构和程序运行时(执行到main函数)时的....
    的头像 STM32嵌入式开发 发表于 05-23 10:36 337次 阅读

    开源轻量级单片机命令行交互项目

    相关的设置在按下sapce键选中后,按enter可进行相关参数配置。然后让 RT-Thread 的包....
    的头像 小麦大叔 发表于 05-23 09:52 331次 阅读

    申请函数kmalloc、kzalloc、vmalloc区别说明

    我们都知道在用户空间动态申请内存用的函数是 malloc(),这个函数在各种操作系统上的使用是一致的....
    的头像 Linux内核补给站 发表于 05-19 16:13 357次 阅读

    Tampermonkey Chrome脚本扩展

    ./oschina_soft/tampermonkey.zip
    发表于 05-18 15:00 43次 阅读
    Tampermonkey Chrome脚本扩展