二叉树题目:结点与其祖先之间的最大差值
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法一
- 思路和算法
- 代码
- 复杂度分析
- 解法二
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:结点与其祖先之间的最大差值
出处:1026. 结点与其祖先之间的最大差值
难度
5 级
题目描述
要求
给定二叉树的根结点 root \texttt{root} root,找出存在于不同结点 a \texttt{a} a 和 b \texttt{b} b 之间的最大值 v \texttt{v} v,其中 v = |a.val - b.val| \texttt{v = |a.val - b.val|} v = |a.val - b.val|,且 a \texttt{a} a 是 b \texttt{b} b 的祖先。
如果 a \texttt{a} a 的任何子结点是 b \texttt{b} b,或者 a \texttt{a} a 的任何子结点是 b \texttt{b} b 的祖先,那么 a \texttt{a} a 是 b \texttt{b} b 的祖先。
示例
示例 1:

输入: root = [8,3,10,1,6,null,14,null,null,4,7,13] \texttt{root = [8,3,10,1,6,null,14,null,null,4,7,13]} root = [8,3,10,1,6,null,14,null,null,4,7,13]
输出: 7 \texttt{7} 7
解释:
我们有若干结点与其祖先的差值,其中一些如下:
|8 - 3| = 5 \texttt{|8 - 3| = 5} |8 - 3| = 5
|3 - 7| = 4 \texttt{|3 - 7| = 4} |3 - 7| = 4
|8 - 1| = 7 \texttt{|8 - 1| = 7} |8 - 1| = 7
|10 - 13| = 3 \texttt{|10 - 13| = 3} |10 - 13| = 3
在所有可能的差值中,最大值 7 \texttt{7} 7 由 |8 - 1| = 7 \texttt{|8 - 1| = 7} |8 - 1| = 7 得出。
示例 2:

输入: root = [1,null,2,null,0,3] \texttt{root = [1,null,2,null,0,3]} root = [1,null,2,null,0,3]
输出: 3 \texttt{3} 3
数据范围
- 树中结点数目在范围 [2, 5000] \texttt{[2, 5000]} [2, 5000] 内
- 0 ≤ Node.val ≤ 10 5 \texttt{0} \le \texttt{Node.val} \le \texttt{10}^\texttt{5} 0≤Node.val≤105
解法一
思路和算法
二叉树中的每个结点对应一条从根结点到该结点的路径,路径存在最大结点值和最小结点值。对于每个结点,该结点与其祖先之间的最大差值可能是以下两种情况之一:
-
路径上的最大结点值与当前结点值之差;
-
当前结点值与路径上的最小结点值之差。
可以使用深度优先搜索计算二叉树中的每个结点与其祖先之间的最大差值。从根结点开始遍历全部结点,由于同一条路径上的结点的遍历顺序是从上到下,在访问到一个结点时,该结点的所有祖先结点都已经被访问过,因此可以得到从根结点到该结点的路径上的最大结点值和最小结点值,计算当前结点与其祖先之间的最大差值。
在访问一个结点之后,对于其非空子结点,更新从根结点到子结点的路径上的最大结点值和最小结点值,对子结点继续遍历。
遍历结束之后,即可得到二叉树中结点与祖先之间的最大差值。
题目要求计算差值的两个结点应满足两个结点不同且一个结点是另一个结点的祖先。上述做法虽然没有考虑计算差值的两个结点是否相同,但是也能得到正确的结果,理由如下。
由于给定的二叉树的结点数目至少为 2 2 2,因此一定存在两个不同的结点且这两个结点之间存在祖先和后代的关系。任何一个结点与其自身的差值一定是 0 0 0。对于两个不同的结点,如果结点值相同则差值等于 0 0 0,如果结点值不同则差值大于 0 0 0,即差值一定不会小于 0 0 0,因此一定存在两个不同的结点,这两个结点之间存在祖先和后代的关系且这两个结点值之差的绝对值等于最大差值。
代码
class Solution {int maxDiff = 0;public int maxAncestorDiff(TreeNode root) {dfs(root, root.val, root.val);return maxDiff;}public void dfs(TreeNode node, int maxValue, int minValue) {int currDiff = Math.max(maxValue - node.val, node.val - minValue);maxDiff = Math.max(maxDiff, currDiff);TreeNode left = node.left, right = node.right;if (left != null) {int leftMaxValue = Math.max(left.val, maxValue);int leftMinValue = Math.min(left.val, minValue);dfs(left, leftMaxValue, leftMinValue);}if (right != null) {int rightMaxValue = Math.max(right.val, maxValue);int rightMinValue = Math.min(right.val, minValue);dfs(right, rightMaxValue, rightMinValue);}}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是栈空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)。
解法二
思路和算法
也可以使用广度优先搜索计算二叉树中结点与祖先之间的最大差值。从根结点开始遍历全部结点,访问结点的顺序为层数递增的顺序,遍历过程中,对于每个结点,得到该结点对应的从根结点到该结点的路径上的最大结点值和最小结点值,计算该结点与其祖先之间的最大差值。
为了记录每个结点对应的从根结点到该结点的路径上的最大结点值和最小结点值,需要使用三个队列,分别存储结点、路径上的最大结点值和路径上的最小结点值,这三个队列分别为结点队列、最大值队列和最小值队列,初始时将根结点入结点队列,将根结点值入最大值队列和最小值队列。每次将一个结点、一个最大值和一个最小值分别从结点队列、最大值队列和最小值队列出队列,计算当前结点与其祖先之间的最大差值。对于当前结点的非空子结点,计算从根结点到子结点的路径上的最大结点值和最小结点值,然后将子结点以及子结点对应的最大结点值和最小结点值分别入结点队列、最大值队列和最小值队列。
遍历结束之后,即可得到二叉树中结点与祖先之间的最大差值。
代码
class Solution {public int maxAncestorDiff(TreeNode root) {int maxDiff = 0;Queue<TreeNode> nodeQueue = new ArrayDeque<TreeNode>();Queue<Integer> maxNode = new ArrayDeque<Integer>();Queue<Integer> minNode = new ArrayDeque<Integer>();nodeQueue.offer(root);maxNode.offer(root.val);minNode.offer(root.val);while (!nodeQueue.isEmpty()) {TreeNode node = nodeQueue.poll();int maxValue = maxNode.poll();int minValue = minNode.poll();int currDiff = Math.max(maxValue - node.val, node.val - minValue);maxDiff = Math.max(maxDiff, currDiff);TreeNode left = node.left, right = node.right;if (left != null) {nodeQueue.offer(left);maxNode.offer(Math.max(left.val, maxValue));minNode.offer(Math.min(left.val, minValue));}if (right != null) {nodeQueue.offer(right);maxNode.offer(Math.max(right.val, maxValue));minNode.offer(Math.min(right.val, minValue));}}return maxDiff;}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是队列空间,队列内元素个数不超过 n n n。
相关文章:
二叉树题目:结点与其祖先之间的最大差值
文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题:结点与其祖先之间的最大差值 出处:1026. 结点与其祖先之间的最大差值 难度 5 级 题目描述 要求 给…...
平衡树 - splay
相比于之前的普通平衡树进行左旋右旋来比,splay的适用性更高,使用更广泛。 核心函数rotate、splay函数,其它的根据需要进行修改。 int n, m; struct Node {int s[2], p, v, cnt; // 左右儿子、父节点、值、出现数量int size, flag; // 子树大…...
Spring Validation实践及其实现原理
Bean Validation 2.0 注解 校验空值 Null:验证对象是否为 null NotNull:验证对象是否不为 null NotEmpty:验证对象不为 null,且长度(数组、集合、字符串等)大于 0 NotBlank:验证字符串不为 nul…...
Java核心知识点整理大全18-笔记
Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全3-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全4-笔记-CSDN博客 Java核心知识点整理大全5-笔记-CSDN博客 Java核心知识点整理大全6…...
vue 富文本编辑器多图上传
首先我使用的富文本编辑器是vue-quill-editor 使用npm进行下载 npm install vue-quill-editor --save当然也可以按照官方的方法下载,到官方 因为我是在原有老项目上开发的使用的组件库是ant-design-vue 1x版,当然使用其他组件库也可以 然后还有重要的一…...
简易地铁自动机售票系统实现(C++)
该程序具有以下功能 (1) 一个地铁路线类 Router,包含路线编号,途中的各个站点。可以新增、删除、查询路线,可以根据线路名称,显示线路图片。 (2) 一个地图类 Map,可以显示所有可以乘坐的地铁站名,以及线路…...
【Spark入门】基础入门
【大家好,我是爱干饭的猿,本文重点介绍Spark的定义、发展、扩展阅读:Spark VS Hadoop、四大特点、框架模块、运行模式、架构角色。 后续会继续分享其他重要知识点总结,如果喜欢这篇文章,点个赞👍ÿ…...
【自制开源】实时调参,手写字生成神器!大学生福音,告别繁琐的手写报告。
HandwritingGenerator HandwritingGenerator 是一个使用 PyQt6 制作的手写文本图片生成器。 该工具允许用户自定义多种效果,通过在左边配置效果参数,右边实时预览,并在调整好后输出图片。 效果预览 软件界面预览:一封情书&#x…...
Python 进阶(十一):高精度计算(decimal 模块)
《Python入门核心技术》专栏总目录・点这里 文章目录 1. 导入decimal模块2. 设置精度3. 创建Decimal对象4. 基本运算5. 比较运算6. 其他常用函数7. 注意事项8. 总结 大家好,我是水滴~~ 在进行数值计算时,浮点数的精度问题可能会导致结果的不准确性。为了…...
MCU常用文件格式
1. asm文件 asm是汇编语言源程序的扩展名,.asm文件是以asm作为扩展名的文件,是汇编语言的源程序文件。汇编语言(Assembly Language)是面向机器的程序设计语言,是利用计算机所有硬件特性并能直接控制硬件的语言。在汇编语言中,用助…...
【机器学习】On the Identifiability of Nonlinear ICA: Sparsity and Beyond
前言 本文是对On the Identifiability of Nonlinear ICA: Sparsity and Beyond (NIPS 2022)中两个结构稀疏假设的总结。原文链接在Reference中。 什么是ICA(Independent component analysis)? 独立成分分析简单来说,就是给定很多的样本X,通…...
RBAC(Role-Based Access Control,基于角色的访问控制)
1. RBAC核心概念 RBAC(Role-Based Access Control,基于角色的访问控制)是一种广泛应用于软件和系统中的权限管理模型。它通过将用户与角色关联,再将角色与访问权限关联,来管理用户对系统资源的访问。RBAC模型的主要特…...
C++const指针的两种用法
const int *p &a; 指向const变量的指针 指向const变量的指针const修饰的变量,只能由指向const变量的指针去指向 p &a1;const的位置,必须在*的左边指向const变量的指针,可以被改变,可以指向别的变量可以指向普通变量&am…...
【Proteus仿真】【51单片机】智能垃圾桶设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器,使用报警模块、LCD1602液晶模块、按键模块、人体红外传感器、HCSR04超声波、有害气体传感器、SG90舵机等。 主要功能: 系统运行后…...
【Windows】执行tasklist/taskkill提示“错误:找不到”或者“ERROR: not found”的解决方案
原因 由于WinMgmt异常导致起不来,而WinMgmt是SVCHOST进程中的WMI服务,解决这个问题需要停止之后再重新启动。 WinMgmt是Windows 2000客户端管理的核心组件,当客户端应用程序连接或当管理程序需要它本身的服务时,这个进程就会初始…...
MS2630——Sub-1 GHz、低噪声放大器芯片
产品简述 MS2630 是一款 Sub-1 GHz 低功耗、低噪声放大器 (LNA) 芯 片。芯片采用先进制造工艺,采用 SOT23-6 的封装形式。 主要特点 ◼ 典型噪声系数: 1.57dB ◼ 典型功率增益: 16.3dB ◼ 典型输出 P1dB : -9.2dBm…...
车载以太网-数据链路层-MAC
文章目录 车载以太网MAC(Media Access Control)车载以太网MAC帧格式以太网MAC帧报文示例车载以太网MAC层测试内容车载以太网MAC(Media Access Control) 车载以太网MAC(Media Access Control)是一种用于车载通信系统的以太网硬件地址,用于在物理层上识别和管理数据包的传…...
Tomcat源码分析
Tomcat源码分析与实例 Tomcat是一个开源的Java Web服务器,它提供了一种简单的方式来部署和运行Java Web应用程序。本文将详细介绍Tomcat的源码分析和实例。 1. Tomcat源码分析 1.1 目录结构 Tomcat的源码目录结构如下: tomcat-x.y.z/ ├── bin/ ├…...
计算机视觉面试题-02
图像处理和计算机视觉基础 什么是图像滤波?有哪些常见的图像滤波器? 图像滤波是一种通过在图像上应用滤波器(卷积核)来改变图像外观或提取图像特征的图像处理技术。滤波器通常是一个小的矩阵,通过在图像上进行卷积…...
力扣日记11.27-【二叉树篇】二叉树的最大深度
力扣日记:【二叉树篇】二叉树的最大深度 日期:2023.11.27 参考:代码随想录、力扣 104. 二叉树的最大深度 题目描述 难度: 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
