算法通过村第八关-树(深度优先)白银笔记|深度和高度问题
文章目录
- 前言
- 1. 最大深度问题
- 2. 判断平衡树
- 3. 最小深度
- 4. N叉树的最大深度
- 总结
前言
提示:我的整个生命,只是一场为了提升社会地位的低俗斗争。--埃莱娜·费兰特《失踪的孩子》
这一关我们看一些比较特别的题目,关于二叉树的深度和高度问题。这些对递归的考察更高些,要注意了。
给你一个二叉树:
我们看下力扣的相关题目,这些是关于深度和高度的问题。
推荐题目⭐⭐⭐⭐:
104. 二叉树的最大深度 - 力扣(LeetCode)
110. 平衡二叉树 - 力扣(LeetCode)
111. 二叉树的最小深度 - 力扣(LeetCode)
1. 最大深度问题
参考题目介绍:104. 二叉树的最大深度 - 力扣(LeetCode)
首先最大深度:根节点到最远叶子节点的最长路径上的节点数。说明叶子节点是没有子节点的。
我们看看下面这些。(上图的最大深度为3)
对于node(3),最大深度自然是左右子节点+1,左右子节点有可能为空,只要有一个,树的最大高度就是1 + 1 = 2。然后再增加几个节点:
很显然相对于node(20),最大的深度自然是左右子节点+1,左右子节点有可能为空,只要右一个,树的最大高度就是1 + 1 = 2,用代码表示就是:
int depth = 1 + math(leftDepth,rightDepth);
对于3,则是左右子树深度最大的那个再加1,具体谁的更大,则不必管旭,所以对于node(3)的逻辑判断就是:
int leftDepth = getDepth(root.left); //左
int rightDepth = getDepth(root.right); // 右
int depth = 1 + math(leftDept,rightDept); // 中
那么什么时候结束呢?这里仍然是root == null 返回0就行了,至于入参,自然是要处理的子树的根节点root,而返回值则是当前root所在子树的最大高度,所以合在一起就是:
/*** 通过递归计算二叉树的深度** @param root* @return*/public static int maxDepth_1(TreeNode root) {if(root == null) {return 0;}int leftDepth = maxDepth_1(root.left);int rightDepth = maxDepth_1(root.right);return Math.max(leftDepth, rightDepth) + 1;}
上面代码先拿到左右子树的结果,再计算Math.max(left,right) + 1,本质上和后序遍历一样,一次者可以看做事后序遍历的扩展问题。
我们继续看这个题目,如果我们确定树最大有几层是不是也确定了最大深度呢?当然,另一个思路不就来了,我们直接套用层序遍历的代码:
具体细节注意一下:我们这里获取层数,每获取一层,就加一。
/*** 通过层次遍历来求最大深度** @param root* @return*/public static int maxDepth_2(TreeNode root) {// 校验参数if (root == null){return 0;}// 创建空间int res = 0;Queue<TreeNode> queue = new LinkedList<TreeNode>();// 根节点入队,不断的遍历根节点queue.offer(root);while(!queue.isEmpty()){// 获取到每层多少个int size = queue.size();// size == 0 说明这一层遍历完了while(size > 0){// 遍历TreeNode node = queue.poll();if (node.left != null){queue.offer(node.left);}if (node.right != null){queue.offer(node.right);}size--;}res++;}return res;}
2. 判断平衡树
参考题目介绍:110. 平衡二叉树 - 力扣(LeetCode)
补充一个知识点:高度和深度怎么区分?
- 二叉树节点的深度:从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:从该节点到叶子节点的最长简单路径边的条数。
关于根节点的深度是1还是0的问题,不同的地方标准不一样,力扣的题目中都是以根节点的深度为1,其他的我们先不管。
我们接着看一下这个问题:
很显然只要有两次的时候一定是平衡的,因为对于node(3),左右孩子如果只有一个,呢么高度差就是1;如果左右孩子都没有或者都有,则高度差为0。但是如果再加一层呢?
看下图:
对于node(3),需要同时知道自己左右子树的最大高度差是否< 2.
- 当节点root左/右子树的高度差 < 2,则返回节点root的左右子树中最大高度+1(max(left,right) + 1);参考上面的深度和高度对比图思考下,这里为什么取最大高度?
- 当节点root左/右子树的高度差 >= 2;则返回-1,代表此树已经不是平衡树了。
也是就是说:
int left = recur(root.left);
int right = recur(root.right);
return Math.abs(left - right) < 2 ? Math.max(left,right) + 1:-1;
我们此时已经写出了核心代码,假设子树已经不平衡了,我们就不需要再递归下去而是直接返回就行了。例如这个树中的节点20:
综合考虑几种情况,我们看下完整的代码:
/*** 方法1 自下而上** @param root* @return*/public static boolean isBalanced_1(TreeNode root) {return recur(root) == -1;}public static int recur(TreeNode root) {if (root == null){return 0;}int left = recur(root.left);if (left == -1){return -1;}int right = recur(root.right);if (right == -1){return -1;}return Math.abs(left - right) < 2 ? Math.max(left,right) + 1: -1;}
/*** 2.自上而下** @param root* @return*/public static boolean isBalanced_2(TreeNode root) {if (root == null){return true;}return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced_2(root.left) && isBalanced_2(root.right);}public static int depth(TreeNode root){if (root == null){return 0;}return Math.max(depth(root.left),depth(root.right)) + 1;}
3. 最小深度
参考题目介绍:111. 二叉树的最小深度 - 力扣(LeetCode)
既然有最大深度,可能会有最小深度?这不他就来了,怎么找出最小深度呢?
最小深度:从根节点到最接近叶子节点的最短路径上的节点数量。
看下下面这个特殊例子: 答案是 2 【说明】:叶子节点是指没有子节点的节点。
前面两道题涉及到最大深度,这里讲max改成min是不是就可以解决了呢? 不行,你注意看上图:
这里的关键问题是题目中说的:最小深度是从根节点到最近叶子节点的最短路径上的节点数量,也就是说最小深度的一层必须要有叶子节点,不能直接使用。
这里的核心问题仍然是终止条件分析:
- 如果左子树为空,右子树不为空,说明最小深度是1 + 右子树的深度。
- 反之,右子树为空,左子树不为空,最小深度1 + 左子树的深度。
最后如果左右子树都不空,返回左右子树深度最小值+1。
我们看下代码展示😎:
/*** 通过递归计算二叉树的最小** @param root* @return*/public static int minDepth_1(TreeNode root) {if (root == null){return 0;}// 根if (root.left == null && root.right == null){return 1;}// 左int min_depth = Integer.MAX_VALUE;if (root.left != null){min_depth = Math.min(minDepth_1(root.left),min_depth);}// 右if (root.right != null){min_depth = Math.min(minDepth_1(root.right),min_depth);}return min_depth + 1;}
除了递归方式,我们也可以采用层次遍历,只要再遍历时,第一次遇到叶子节点就直接返回,其所在的层次就行,我们可以简单改下层序遍历的方法:
/*** 通过层次遍历来求最大深度** @return*/public static int minDepth_2(TreeNode root) {// 参数检验if (root == null){return 0;}// 创建空间int minDepth = 0;Queue<TreeNode> queue = new LinkedList<>();// 根节点入队,不断循环遍历queue.offer(root);while(!queue.isEmpty()){// 获取队列的长队 这个长度说明这一层有多少个节点int size = queue.size();minDepth++;for(int i = 0; i < size; i++){TreeNode node = queue.poll();if (node.left == null && node.right == null){return minDepth;}if (node.left != null){queue.offer(node.left);}if (node.right != null){queue.offer(node.right);}}}return 0;}
4. N叉树的最大深度
参考题目介绍:559. N 叉树的最大深度 - 力扣(LeetCode)
这道题不同的地方是将二叉树换成了N叉树,N叉树的节点较多,我们使用List存储,遍历时采用for即可,我们先看看力扣的N叉树的定义:
class Node {public int val;public List<Node> children;public Node() {}public Node(int _val) {val = _val;}public Node(int _val, List<Node> _children) {val = _val;children = _children;}
};
这个题的实现和上个题的最大区别就是在处理子树的问题上面加了个处理List的for循环
代码也很简单🤔:
/*** 递归求N叉树的深度* @param root* @return*/public static int maxDepth_N(NTreeNode root) {if (root == null){return 0;}else if (root.children.isEmpty()){return 1;}else{// 处理子树问题List<Integer> heights = new ArrayList<>();for(NTreeNode item : root.children){heights.add(maxDepth_N(item));}return Collections.max(heights) + 1;}}
当然了,本地还可以使用层序遍历,这个作为拓展感兴趣的话可以试试。
总结
提示:二叉树的深度和高度;N叉树的深度问题;平衡树的判断问题
相关文章:

算法通过村第八关-树(深度优先)白银笔记|深度和高度问题
文章目录 前言1. 最大深度问题2. 判断平衡树3. 最小深度4. N叉树的最大深度总结 前言 提示:我的整个生命,只是一场为了提升社会地位的低俗斗争。--埃莱娜费兰特《失踪的孩子》 这一关我们看一些比较特别的题目,关于二叉树的深度和高度问题。这…...
Redis安装和使用
这里写目录标题 Redis安装和使用一.数据库类型1.关系型数据库2.非关系型数据库3.区别(1)数据存储方式不同(2)扩展方式不同(3)对事务性的支持不同 二.redis简介1.Redis 优点2.哪些数据适合放入缓存中&#x…...

UML基础与应用之面向对象
UML(Unified Modeling Language)是一种用于软件系统建模的标准化语言,它使用图形符号和文本来描述软件系统的结构、行为和交互。在面向对象编程中,UML被广泛应用于软件系统的设计和分析阶段。本文将总结UML基础与应用之面向对象的…...

将 Ordinals 与比特币智能合约集成:第 2 部分
在上一篇文章中,我们展示了一种将 Ordinal 与智能合约集成的方法,即将Ordinal和合约放在同一个 UTXO 中。 今天,我们介绍了一种集成它们的替代方案,即它们位于单独的 UTXO 中。 作为展示,我们开发了一个智能合约&…...
PCL 法线空间采样(C++详细过程版)
法线空间采样 一、概述二、代码实现三、结果展示1、原始点云2、采样结果一、概述 法线空间采样在PCL里有现成的调用函数,具体算法原理和实现代码见:PCL 法线空间采样。为充分了解法线空间采样算法实现的每一个细节和有待改进的地方,使用C++代码对算法实现过程进行复现。 二…...

论文阅读:AugGAN: Cross Domain Adaptation with GAN-based Data Augmentation
Abstract 基于GAN的图像转换方法存在两个缺陷:保留图像目标和保持图像转换前后的一致性,这导致不能用它生成大量不同域的训练数据。论文提出了一种结构感知(Structure-aware)的图像转换网络(image-to-image translation network)。 Proposed Framework…...

CNC 3D浮雕 Aspire 11.55 Crack
Aspire 提供了功能强大且直观的软件解决方案,用于在 CNC 铣床上创建和切割零件。有用于 2D 设计和计算 2D 刀具路径的工具,例如仿形、型腔加工和钻孔以及 2.5D 刀具路径,包括:V 形雕刻、棱镜雕刻、成型刀具路径、凹槽、 倒角刀具路…...
【Clickhouse2022.02 查询优化】
一、现场场景概述 现场每天每张表入库数据量大约2-4亿条,页面涉及到自定义时间段查询(白天08:00-15:00,夜晚23:00-06:00)与不同时间段(最近一天、一周、一个月和全部)的统计指标查询。 二、主要问题 时间跨度大无查询或查询条件命中数据过多的分页查询场景速度慢 (主要是数据…...

PMP证书在国内已经泛滥了,还有含金量吗?
没有泛滥吧?这个证书现在就是趋向于项目管理人士要去考的呀,也不是考了没用,提升自身个人的能力、找工作方面和晋升加薪方面确实有用呀,不然报名费那么贵,为什么越来越多人考呢? 1、提升自身个人的能力 首…...

SolidJs节点级响应性
前言 随着组件化、响应式、虚拟DOM等技术思想引领着前端开发的潮流,相关的技术框架大行其道,就以目前主流的Vue、React框架来说,它们都基于组件化、响应式、虚拟DOM等技术思想的实现,但是具有不同开发使用方式以及实现原理&#…...

数据采集技术在MES管理系统中的应用及效果
在现代制造业中,MES生产管理系统已成为生产过程中不可或缺的一部分。MES管理系统能够有效地将生产计划、生产执行、质量管理等各个生产环节有机地衔接起来,从而实现生产过程的全面优化。本文将以某车间为例,探讨结合MES系统的数据采集技术的应…...

php函数usort使用方法
在 PHP 中,usort() 函数用于对数组进行排序,它允许你使用自定义的比较函数来确定元素的顺序。以下是 usort() 函数的使用方法: usort(array &$array, callable $cmp_function): bool参数说明: $array:要排序的数…...
35.浅谈贪心算法
概述 相信大家或多或少都对贪心算法有所耳闻,今天我们从一个应用场景展开 假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号? 广播台覆盖地区k1北京、上海、天津…...
QT时间日期定时器类(1.QDate类)【QT基础入门 Demo篇】
使用时候需要包含头文件 创建一个 QDate 实例 设置 QDate 的日期 获取 QDate 的日期 获取当前是周几 判断 QDate 的有效性 格式化 QDate 的显示字符串 计算 QDate 的差值 QDate显示格式 年月日转换时间戳时间戳转换年月日 QDate相关…...

记一次实战案例
1、目标:inurl:news.php?id URL:https://www.lghk.com/news.php?id5 网站标题:趋时珠宝首饰有限公司 手工基础判断: And用法 and 11: 这个条件始终是为真的, 也就是说, 存在SQL注入的话, 这个and 11的返回结果必定是和正常页…...

Serv-U FTP服务器结合cpolar内网穿透实现共享文件并且外网可远程访问——“cpolar内网穿透”
文章目录 1. 前言2. 本地FTP搭建2.1 Serv-U下载和安装2.2 Serv-U共享网页测试2.3 Cpolar下载和安装 3. 本地FTP发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 科技日益发展的今天,移动电子设备似乎成了我们生活的主角,智能…...

EasyWindow - Android 悬浮窗框架
官网 https://github.com/getActivity/EasyWindow 项目介绍 本框架意在解决一些极端需求,如果是普通的 Toast 封装推荐使用 Toaster 集成步骤 如果你的项目 Gradle 配置是在 7.0 以下,需要在 build.gradle 文件中加入 allprojects {repositories {/…...

tp5连接多个数据库
一、如果你的主数据库配置文件都在config.php里 直接在config.php中中定义db2: 控制器中打印一下: <?php namespace app\index\controller; use think\Controller; use think\Db; use think\Request; class Index extends Controller {public fun…...

SAP PO运维(一):系统概览异常处理
打开SAP PIPO Netweaver Administration界面,系统概览下显示异常: 参考SAP note: 2577844 - AS Java Monitoring and Logging parametrization best practice service/protectedwebmethods = SDEFAULT -GetVersionInfo -GetAccessPointList -ListLogFiles -ReadLogFile -Para…...

安全厂商安恒信息加入龙蜥社区,完成 与 Anolis OS 兼容适配
近日,杭州安恒信息技术股份有限公司(以下简称“安恒信息”)签署了 CLA(Contributor License Agreement,贡献者许可协议),正式加入龙蜥社区(OpenAnolis),并成为…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

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

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...