代码随想录 Day 18 | 【第六章 二叉树 part06】530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

听故事学语言 · 数据结构篇 · 第五章 藏在文件里的顺序与链 数据结构篇第五章,工业章一,前四章家当的实战回门。拖动进度条为什么秒跳,MP4 登记簿记位置供直达;FAT 文件分配表,链式存储的逻辑、数组实现的身体,1977 年马克·麦克唐纳为软盘设计它;进程档案链表轮转,一头进一头出,内核偏爱链表的连接自由;浏览器后退键,教科书的双向链表对工业界的数组加游标,同一个队形,两种站位法,谁赢谁的战场。 阅读详情

一、530.二叉搜索树的最小绝对差

需要领悟一下二叉树遍历上双指针操作,优先掌握递归

1. 直白想法

        采用中序遍历,将这棵树转变为一个递增的有序数组,再对数组进行遍历。计算相邻两个数之间的差值,返回最小的绝对差。

2. 双指针法

        在直白想法的基础上优化,通过定义一个指针指向前一个节点,另一个指针指向当前节点,用两个指针相减直接得到绝对差,就不需要将树转化为数组再进行遍历了。

(1)定义一个变量result记录相邻节点的最小绝对差,将其初始化为一个最大值。定义一个指针pre,将其初始化为None。

(2)定义函数的参数和返回值。因为本题定义了全局变量result和pre,所以递归函数不需要返回值。传入cur,作为当前遍历的节点。

(3)确定终止条件。遍历到当前节点为空,不需要返回值,所以只写一个return。

(4)单层递归遍历。本题采用中序遍历,先向左遍历;再处理中间节点,如果pre节点不为空,那么就可以记录cur和pre节点的差值,更新result采用min函数,取差值和原始result中间的最小值,最后为了使cur和pre始终紧密相连,所以更新pre指向cur;接下来可以向右递归。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.result = float('inf')
        self.pre = None
    def traversal(self, cur):
        if cur is None:
            return 

        # left:
        self.traversal(cur.left)

        # middle:
        if self.pre is not None:
            self.result = min(self.result, cur.val-self.pre.val)
        self.pre = cur

        # right:
        self.traversal(cur.right)
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        self.traversal(root)
        return self.result
        

二、501.二叉搜索树中的众数

和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。

1. 双指针法

(1)定义pre指针,找到当前遍历节点的前一个节点;定义count,记录元素出现的频率;定义max_count,记录当前遍历节点中出现频率最高的;定义结果集数组result,用于存放结果集。

(2)定义递归函数,传入的是二叉树根节点,返回值为void,因为遍历整个二叉树,并且在遍历过程中直接对元素进行统计,结果也存放在result里了,因此不需要返回值。

(3)终止条件为cur遇到空,直接返回即可。

(4)中序遍历:

        左:直接递归遍历;

        中:1)if:如果pre指针为null,即递归遍历的第一个元素,因此count等于1,也就是该元素目前出现的频率为1;elif:如果pre指针指向的元素等于cur指针指向的元素,那么count+=1,也就是这个元素出现的频率加1。else:说明pre和cur不相等,所以count变回1;

                2)递归:pre=cur;

                3)收获结果:如果count等于max_count,那么将其放进结果集;如果count大于max_count,那么将max_count更新为count,由于max_count更新,那么说明之前结果集的元素不是我们真正想要的结果,所以清空result结果集,再将当前结果放进结果集。这样完成了result的实时更新。

        右:向右遍历,最后返回。

2. 代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.result = []
        self.pre = None
        self.count = 0
        self.max_count = 0

    def traversal(self, cur):
        if cur is None:
            return

        # left:
        self.traversal(cur.left)

        # middle:
        if self.pre is None:
            self.count = 1
        elif cur.val == self.pre.val:
            self.count += 1
        else: self.count = 1

        self.pre = cur 

        if self.count == self.max_count:
            self.result.append(cur.val)

        if self.count > self.max_count:
            self.max_count = self.count
            self.result = []
            self.result.append(cur.val)

        # right:
        self.traversal(cur.right)

    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.traversal(root)
        return self.result

三、236. 二叉树的最近公共祖先

本题其实是比较难的,可以先看我的视频讲解

1. 解题思路

自底向上遍历,第一个交汇的节点就是最近公共祖先。而二叉树只能从根节点开始遍历,但回溯的过程可以让我们从底向上去遍历树。

2. 后序遍历

        后序遍历:左右中的顺序,左/右中有p或q就向上返回,因此左子树中如果不为空,说明包含p或q,右子树不为空说明包含q或p,那么中间的这个节点就是最近的公共祖先。 

      

3. 代码实现

(1)定义函数traversal,返回值为二叉树的公共祖先,所以返回节点TreeNode。传入参数为根节点、p和q。

(2)终止条件:遍历的节点为空,直接返回null;如果root等于p或q,则将节点返回。

(3)后序遍历:

        左:向左遍历,传入left和q、p,告诉我们左子树是否存在p或q;

        右:向右遍历,传入right和q、p,告诉我们右子树是否存在p或q;

        中:如果左且右不为空,那么说明二者出现了p或q;如果左为空且右不为空,那么说明右子树出现了p或q,将右向上返回;如果左不为空且右为空,那么说明左子树出现了p或q,将左向上返回;左右均为空,返回null。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root is None: return None
        if root == q or root == p: return root
        
        # left:
        left = self.lowestCommonAncestor(root.left, p, q)
        # right:
        right = self.lowestCommonAncestor(root.right, p, q)
        # middle:
        if left is None and right is None: return None
        if left is None and right is not None: return right
        if left is not None and right is None: return left
        if left is not None and right is not None: return root

Hi3516CV610 YOLOv8模型转换与部署实战:从源码到板端推理全流程解析 本文详细解析了将YOLOv8模型部署到Hi3516CV610开发板的全流程。内容涵盖从Ubuntu环境搭建、模型获取与验证,到关键的PyTorch模型转换为ONNX格式,并利用海思工具链量化生成板端可执行的.wk文件。最后,指导开发者编写板端C程序,完成视频流处理、NNIE推理及结果后处理,并提供了部署调试与性能优化的实用技巧。 阅读详情

相关推荐

TI 实时操作系统SYS/BIOS使用总结

1:概述: SYS/BIOS 是一个可扩展的实时的操作系统。具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片)。能够实现系统的模块化并可裁剪。 最大的特点就是:实时。 2:XDCtools: XDCtools 是SYS/BIOS引用的一种实时的软件组件技术(RTSC),它包括一些有用的工具,标准的AP

带头奋青的博客 5万+

代码随想录算法训练营day18(python版)|第六章 二叉树part06| 530.二叉搜索树的最小绝对差·501.二叉搜索树中的众数·236. 二叉树的最近公共祖先

530.二叉搜索树的最小绝对差需要领悟一下二叉树遍历上双指针操作,优先掌握递归思路BST 中序遍历是升序;最小绝对差只会出现在中序相邻节点之间;遍历时维护prev(上一个访问的值)并滚动更新答案。

qq_43752779的博客 705

Buck变换器中EA模块的优化设计与稳定性提升策略

本文深入探讨了Buck变换器中误差放大器(EA)模块的核心作用与优化设计。作为系统的“大脑”,EA模块的性能直接决定了电源的稳定性与动态响应。文章详细分析了EA的电路结构、工作原理,并重点阐述了通过优化增益、带宽和相位裕度来提升系统稳定性的策略,同时提供了实用的设计技巧与仿真验证方法。

weixin_29189381的博客 423

代码随想录 day18 二叉树 part06

需要领悟一下二叉树遍历上双指针操作,优先掌握递归。

2401_88561446的博客 282

【COMSOL】将一个面上数据导出CSV或txt格式的方法

在COMSOL中参数化扫描后,把一个面上或体里的数据按照CSV或TXT格式导出的方法。

dave496206的博客 2990

基于PCA的故障诊断方法(matlab)

1. PCA原理分析 PCA的原理主要是将原始数据进行降维。其具体工作原理参照:CodingLabs - PCA的数学原理 2. 数据预处理 训练数据集(只有正样本)为维数据,即有n个采样值,每个采样值有m个特征。 2.1 数据归一化 将数据X针对每个特征归一化为均值为0,均方根为1的数据。 其中: 3. PCA降维 3.1 首先求取协方差矩阵 协方差矩阵的公式为: 计算出来的协方差矩阵为特征m*m维矩阵。 3.2 求取特征值和特征向量 求取协方差矩阵R的特征值.

tangxianyu的博客 1万+

day18 第六章 二叉树part06

遍历边还是整棵树,取决于是否要同时处理左右子树的返回结果。学会在递归遍历的过程中如何记录前后两个指针。二叉搜索树:有序数组---中序遍历。530.二叉搜索树的最小绝对差。236. 二叉树的最近公共祖先。501.二叉搜索树中的众数。普通二叉树:无序数组。

mvufi的博客 236

openCv +3.4.0 车牌定位(C++版本)

#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc.hpp> #include "opencv2/shape.hpp" using namespace ...

Bamboo265925的博客 2337

代码随想录算法训练营DAY18第六章 二叉树part06

【代码】代码随想录算法训练营DAY18第六章 二叉树part06。

2401_88089822的博客 73

ParaView: 从 2 或 3 个标量创建向量

ParaView: 从 2 或 3 个标量创建向量

希望我的博客,能帮上你解决学习中工作中所遇到的问题 585

使用conda环境python3.13和python3.12下安装vllm过程记录

使用conda环境python3.13和python3.12下安装vllm过程记录

没刮胡子的程序员专栏 885

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

weixin_44218929的博客 187

智能制造之物料详解

制造业业务系统中的物料流转贯穿需求、采购、生产到交付全流程,各系统协同实现精准追踪。需求阶段由CRM/ERP/PLM生成物料计划;采购入库阶段SCM/WMS/QMS完成采购质检;生产阶段MES/APS协调领料加工;成品交付阶段WMS/SCM处理出库物流。整个流程以BOM为蓝图,ERP为调度中心,通过数据联动实现物料状态、位置和数量的全链路可追溯。

cdfunlove的博客 655

pandas 深度入门:从数据结构到一份真实销售报表

本文系统讲解Pandas核心应用,从三分钟安装到完整月度报表生成,涵盖数据读取、清洗、筛选、分组聚合、表连接、透视表与时间序列等13个关键环节。强调“先看数据再动手”,掌握Series/DataFrame/Index结构本质,熟练运用loc/iloc、merge校验、agg/transform区别,通过真实案例实现高效报表自动化,告别手动Excel操作。最后提供性能优化与高频报错解决方案,助力读者快速上手,真正实现“写二十行代码,跑三秒出结果”。

信息安全领域优质创作者|操作系统领域专家 281

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

数据结构的基本概念和算法的初步认识

本文系统阐述数据结构与算法的基础概念,涵盖数据、数据元素、数据对象的层次关系,数据结构的三要素(逻辑结构、存储结构、数据运算),以及抽象数据类型。重点解析算法的特性与设计要求,并深入讲解时间复杂度分析的核心——大O表示法,通过“只保留最高阶项、忽略常数系数、取最坏情况”三大原则,结合实例剖析O(1)、O(n)等常见时间复杂度,揭示算法效率的本质评估方法。

ACH_YYX的博客 188

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

数据结构:9.Map和Set

有的讲解会说这里key是标识作用,这种说法其实没有太大意义,就算知道了他是标识value的作用又如何,在实际的使用过程中,我们只会根据具体的效果选择使用的方法等,不会执着于“标识”这种说法。2.由于哈希函数的设计原则太过理论,它仅仅是在认为:这些通过关键码算出来的index不同 的情况下设计的,然而这种理论化的设计原则在遇到冲突时,恰恰就出现了问题,而我们能做的,就是降低冲突率。虽然哈希表的使用过程中存在冲突,但是在实际的使用过程中,哈希表的冲突率是不高的,冲突的个数是可控的。

2602_95646088的博客 201

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 343

排序算法深度笔记(上):比较类排序的思想演进与代码实现

与。本文聚焦前者 —— 也就是通过元素间两两比较来确定相对顺序的排序算法,从最朴素的 O (n²) 基础排序,到工业级主流的 O (nlogn) 进阶排序,逐层拆解设计思想、带注释的代码实现与边界细节。当我们理解了比较排序的性能边界,也就自然引出了非比较排序的存在意义。所有代码均遵循统一的实现规范:入口函数前置空数组与单元素边界校验,基于数组原地修改,主函数附带可直接运行的测试用例,与练习代码风格完全对齐。

2401_87069538的博客 611

CF2283F[数据结构]

首先考虑一种暴力解法,当我们建好i之前的图后,当我们添加i的时候,区间[li,ri]中的点都会向i建边,但是这些点中,如果有某两个顶点l,r,满足l<r,那么l就可以通过r间接到达i,因此可以删除l到i的边;初始时我们令所有点放入set中,然后对于每一个i的处理,我们将集合中仍在[l,r]的范围的点弹出,并且将f设置为i,这样我们就得到了所有点的最小跳板;对于每个区间[l,r] 我们要计算这下下标中的f(v)中大于r的数目有多少个;我们令f(v)表示顶点v可到达的最小的顶点;

蒟蒻 138

笔记-论数据结构2

typedef 数据类型 别名return 0;typedef也经常用在结构体上:每次声明结构体变量都要写struct关键字,很麻烦,而且逻辑上也很难受,typedef可以解决这个问题。int x;int y;p.x = 5;p.y = 10;return 0;而利用typedef解决有两种解法:typedef struct 结构体名数据类型 变量名;数据类型 变量名;……}别名;数据类型 变量名;数据类型 变量名;……}别名;实际的运用int x;

fish_zzzz的博客 111

【数据结构-3】算法美学之降复杂度

在while循环的循环体内,首先用临时变量保存最后一个位置的数据,再通过for循环把所有元素往后移动一位,最后把tmp中保存的值放到下标为0的位置上去。方法二的思路是:创建新数组,让原数组中后k个数据移动到新数组中前面的位置,让原数组中前numsSize-k个数据移动到新数组中后面的位置,这。这段代码的思路是:三次逆置,第一次逆置前numsSize-k个数据,第二次逆置后k个数据,最后整体逆置。这篇博文分享一道解法不一的算法题,求解过程的目的在于降低算法的时间复杂度,题源力扣。,属于空间换时间的操作。

weixin_44218929的博客 85

【数据结构-2】顺序表的实现

线性表是一种数据结构,它分为逻辑结构和物理结构,在逻辑结构上线性表是呈线性的,数据是是连续存储的;在物理结构(物理空间)上,线性表不一定是连续存储的。线性表的实现,主要分为数组和链式结构。顺序表是线性表的一种实现方式,顺序表在逻辑结构和物理结构上都是连续的。顺序表的底层实现是数组。

weixin_44218929的博客 208

数据结构:排序

将一组无序的记录(数据元素),按照某个关键字(key)递增或递减的顺序重新排列。

2502_92937908的博客 467

Python 开发的实践:从数据结构选型到框架决策

规模多大?决定用list还是set,Pandas 还是 Polars。瓶颈在哪?I/O 密集用异步,CPU 密集用进程/自由线程,内存受限用列式与惰性执行。代价是什么?消除手动维护窗口的出错面,TaskGroup消除失败任务不被取消的泄漏,消除 N+1,Protocol消除为类型约束而引入的继承层级——每个选择都在消除某类代价,同时也引入新的约束。能回答这三个问题,比记住更多 API 更有用。愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意!

weixin_45809780的博客 379

头歌 数据结构——C&C++线性表实训

本系列任务围绕线性表的链式实现,依次完成顺序构建、逆序构建、排序插入、查找、删除、求长度及栈、队列、集合等应用。通过动态内存分配与指针操作,掌握单链表的基本操作与实际应用,涵盖插入、删除、遍历、搜索等核心功能,最终实现数据结构在典型场景中的灵活运用。

一名敲代码的苦13程序员 238

CDGA DMBOK 第5章——数据建模和设计:如何将业务需求转化为规范的数据结构

本章系统阐述数据建模与设计的核心方法,强调将业务需求转化为规范数据结构的全过程。重点涵盖数据模型三层次(概念、逻辑、物理)、实体关系模型(ER)及主键、外键等核心要素,深入解析第一至第三范式,阐明规范化在消除冗余、保障数据一致性的关键作用,并介绍反规范化在性能优化中的合理应用。通过“概念看业务、逻辑看结构、物理看实现”的逻辑框架,实现从需求到数据库落地的完整闭环。

积跬步,慕至千里的博客 307
上一篇: 代码随想录 Day 17 | 【第六章 二叉树 part05】654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
下一篇: 代码随想录 Day 20 | 【第六章 二叉树part07】235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
Accept17
博客等级 码龄4年 479粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值