当前位置: 首页 > article >正文

【LeetCode刷题日记】二叉搜索树 的中序遍历 + 前驱指针,一套模板解决530.最小绝对差|501.二叉搜索树中的众数

个人主页北极的代码欢迎来访作者简介java后端学习者❄️个人专栏苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺前言大家好我是代码不加冰又来到了我们每日的刷题环节昨天我们具体了解了二叉搜索树相关的知识然后刷了两道算法题进行了加深理解今天我们继续看看二叉搜索树的其他引申题目。摘要本文介绍了二叉搜索树的两道算法题解法。530题通过中序遍历将BST转为有序数组利用前驱节点实时计算相邻节点差值找出最小绝对差。501题同样利用中序遍历特性统计相邻重复元素出现次数动态更新众数结果集。两题均采用递归中序遍历时间复杂度O(n)空间复杂度O(1)不考虑递归栈。核心思路都是利用BST中序遍历的有序性将树结构问题转化为线性序列问题求解。题目背景530.二叉搜索树的最小绝对差给你一个二叉搜索树的根节点root返回树中任意两不同节点值之间的最小差值。差值是一个正数其数值等于两值之差的绝对值。示例 1输入root [4,2,6,1,3]输出1示例 2输入root [1,0,48,null,null,12,49]输出1提示树中节点的数目范围是[2, 104]0 Node.val 105题目解析题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。注意是二叉搜索树二叉搜索树可是有序的。遇到在二叉搜索树上求什么最值啊差值之类的我们就把它想成在一个有序数组上求最值求差值这样就简单多了。那么二叉搜索树采用中序遍历其实就是一个有序数组。在一个有序数组上求两个数最小差值最直观的想法就是把二叉搜索树转换成有序数组然后遍历一遍数组就统计出来最小差值了。核心解法其实就是利用我们上一道题目的方法都是一样的利用一个前驱节点然后利用中序遍历在遍历过程中实时计算差值无需额外数组存储。原理二叉搜索树的中序遍历结果是一个严格递增的序列。因此任意两个节点的最小差值必然出现在中序遍历的相邻节点之间。代码逻辑1.递归进行中序遍历先遍历左子树再处理当前节点最后遍历右子树。2. 使用prev指针记录上一次访问的节点。3. 每次访问当前节点时若prev不为空则计算node.val - prev.valBST性质保证差值为正并更新全局最小值。首先我们先把要得到的结果定义成一个全局变量初始值定为整数的最大值这样我们后面在进行找最小差值 的时候就不用考虑这个差值有没有可能比我们初始定义的最小值大所以直接定义成整数的最大值之后进行取min。然后就是定义一个前驱节点之后操作中进行实时更新利用前驱节点进行计算差值之后就是递归的逻辑了跟我们前面那题一样唯一变化的就是每次递归的逻辑是要比较当前节点和前驱节点的差值// 当前节点值一定大于前驱节点值BST中序性质 minDiff Math.min(minDiff, node.val - prev.val);题目答案/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val val; * this.left left; * this.right right; * } * } */ class Solution { private int minDiff Integer.MAX_VALUE; // 记录最小差值 private TreeNode prev null; // 记录中序遍历的前一个节点 public int getMinimumDifference(TreeNode root) { inorderTraversal(root); return minDiff; } private void inorderTraversal(TreeNode node) { if (node null) return; // 左子树 inorderTraversal(node.left); // 处理当前节点 if (prev ! null) { // 当前节点值一定大于前驱节点值BST中序性质 minDiff Math.min(minDiff, node.val - prev.val); } prev node; // 更新前驱节点 // 右子树 inorderTraversal(node.right); } }题目背景501. 二叉搜索树中的众数501. 二叉搜索树中的众数https://leetcode.cn/problems/find-mode-in-binary-search-tree/给你一个含重复值的二叉搜索树BST的根节点root找出并返回 BST 中的所有 众数即出现频率最高的元素。如果树中有不止一个众数可以按任意顺序返回。假定 BST 满足如下定义结点左子树中所含节点的值小于等于当前节点的值结点右子树中所含节点的值大于等于当前节点的值左子树和右子树都是二叉搜索树示例 1输入root [1,null,2,2]输出[2]示例 2输入root [0]输出[0]提示树中节点的数目在范围[1, 104]内-105 Node.val 105进阶你可以不使用额外的空间吗假设由递归产生的隐式调用栈的开销不被计算在内题目分析其实正常来说一个二叉搜索树是没有重复元素的但既然题目给了我们还是要按照题目的意思来做。众数就不用多解释了高中数学讲过就是出现最多次数的数组。二叉搜索树的众数也就是这棵树中出现频率最多的值。(可能有多个出现相同次数的数)题目给出的定义假定 BST 有如下定义结点左子树中所含结点的值小于等于当前结点的值结点右子树中所含结点的值大于等于当前结点的值左子树和右子树都是二叉搜索树具体的实现思路如果不是二叉搜索树最直观的方法一定是把这个树都遍历了用map统计频率把频率排个序最后取前面高频的元素的集合。这跟我们前面 做过的一道题目一样但这里给出的是二叉搜索树肯定有比较简单的方法。BST的中序遍历结果是一个递增或非递减序列相同的元素一定相邻出现先搞明白这一点然后我们进行递归遍历中序遍历跟前面一样没什么好说的主要就是节点的处理逻辑我们要判断元素出现的次数由于是二叉搜索树相同的元素一定相邻所以我们可以用pre.val node.val这个来计算count使得count1.如果处理的是第一个节点count12.如果都不是那就代表这个元素是一个新的开始重置计数为1.然后更新结果集注意是一边遍历一边更新。if (count maxCount) { // 当前出现次数等于当前最大次数加入结果集 result.add(node.val); } else if (count maxCount) { // 当前出现次数大于最大次数更新maxCount并清空结果集 maxCount count; result.clear(); result.add(node.val); }当countmaxCount的时候我们更新maxCount然后将结果集中之前的元素清空这个新的结果才是众数出现最多次数的元素。count maxCount→ 添加当前值count maxCount→ 清空结果集更新 maxCount添加当前值count maxCount→ 忽略然后就是输出结果题目要求返回int[]数组而我们为了方便利用了List来存储结果因为我们不知道众数有多少个。角色类型原因题目要求返回int[]力扣题目规定的返回类型我们存储结果ListInteger因为不知道几个众数需要动态数组所以最后必须做一次类型转换。ps返回的众数是一个元素只是可能有相同次数的不同元素。复杂度分析复杂度值说明时间复杂度O(n)每个节点恰好访问一次空间复杂度O(h)h 为树的高度递归调用栈空间结果集不计入额外空间其他解法对比解法优点缺点中序遍历实时统计推荐一次遍历完成空间利用率高需要理解 BST 特性遍历HashMap统计适用于普通二叉树思路简单需要额外 O(n) 空间存储频率Morris 遍历空间复杂度 O(1)真正的常量空间实现复杂会临时修改树结构题目答案/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val val; * this.left left; * this.right right; * } * } */ class Solution { private ListInteger result new ArrayList(); // 存储众数结果 private TreeNode pre null; // 中序遍历的前一个节点 private int count 0; // 当前值出现的次数 private int maxCount 0; // 当前众数出现的最大次数 public int[] findMode(TreeNode root) { inorderTraversal(root); // 将 List 转换为 int[] 返回 int[] res new int[result.size()]; for (int i 0; i result.size(); i) { res[i] result.get(i); } return res; } private void inorderTraversal(TreeNode node) { if (node null) return; // 遍历左子树 inorderTraversal(node.left); // 处理当前节点 if (pre null) { // 第一个节点 count 1; } else if (pre.val node.val) { // 与前一个节点值相同计数加1 count; } else { // 遇到新值重置计数为1 count 1; } // 更新结果集 if (count maxCount) { // 当前出现次数等于当前最大次数加入结果集 result.add(node.val); } else if (count maxCount) { // 当前出现次数大于最大次数更新maxCount并清空结果集 maxCount count; result.clear(); result.add(node.val); } // 更新前驱节点 pre node; // 遍历右子树 inorderTraversal(node.right); } }结语如果对你有帮助请点赞关注收藏你的支持就是我最大的鼓励

相关文章:

【LeetCode刷题日记】二叉搜索树 的中序遍历 + 前驱指针,一套模板解决530.最小绝对差|501.二叉搜索树中的众数

🔥个人主页:北极的代码(欢迎来访) 🎬作者简介:java后端学习者 ❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb ✨命运的结局尽可永在,不屈的挑战却不可须臾或…...

Nacos CVE-2021-29442:Spring Boot Actuator未授权访问漏洞深度解析

1. 这个漏洞不是“改个配置就能修好”的那种 Nacos CVE-2021-29442,这个名字在2021年中后期的Java中间件运维圈里,曾让不少团队在凌晨三点被电话叫醒。它不是那种需要你翻文档、查API、调参数的常规问题,而是一个典型的“默认行为埋雷”——…...

miniblink49浏览器内核:企业级打印与PDF生成技术架构深度解析

miniblink49浏览器内核:企业级打印与PDF生成技术架构深度解析 【免费下载链接】miniblink49 a lighter, faster browser kernel of blink to integrate HTML UI in your app. 一个小巧、轻量的浏览器内核,用来取代wke和libcef 项目地址: https://gitco…...

栈以及队列的详细讲解

1.栈的定义以及实现栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。压栈&…...

HashMap 源码解析 底层原理 面试如何回答

HashMap 源码解析 底层原理 面试如何回答 一、参考资料 【Java视频教程,java入门神器(附300道Java面试题剖析)】 https://www.bilibili.com/video/BV1PY411e7J6/?p172&share_sourcecopy_web&vd_source855891859b2dc554eace9de3f28b4…...

线段树入门:算法分析

算法分析线段树采用了分而治之的策略,其点更新、区间更新、区间查询都可以在 时间内完成。树状数组和线段树都用于解决频繁修改和查询的问题,树状数组比线段树更节省空间、代码简单易懂,但是先单数用途更广、更加灵活,凡是可以使用…...

DeepSeek模型版本选择实战手册(2024最新版):从推理延迟、显存占用到LoRA兼容性全拆解

更多请点击: https://intelliparadigm.com 第一章:DeepSeek模型版本选择实战手册(2024最新版):从推理延迟、显存占用到LoRA兼容性全拆解 选择合适的 DeepSeek 模型版本是部署高效、低成本大模型服务的关键前提。2024…...

Gemini企业社会责任实践白皮书(2024独家解密版):覆盖AI伦理、碳足迹追踪与社区赋能的3层合规架构

更多请点击: https://codechina.net 第一章:Gemini企业社会责任实践白皮书(2024独家解密版)概览 本白皮书首次系统披露Google Gemini大模型在2024年度面向环境可持续性、AI伦理治理、数字包容性及社区赋能四大维度的企业社会责任…...

ChatGPT写不出合格投资人邮件?错!真正稀缺的是这5个私募股权语境理解层(附LP偏好词云图谱)

更多请点击: https://intelliparadigm.com 第一章:ChatGPT投资人邮件撰写的核心误区与范式跃迁 许多创业者在使用ChatGPT辅助撰写面向投资人的邮件时,陷入“信息堆砌型”表达陷阱——将产品功能、技术参数、市场数据不加筛选地塞入正文&…...

将taotoken接入openclaw agent工作流的配置要点

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 将taotoken接入openclaw agent工作流的配置要点 在构建基于大模型的智能体应用时,一个稳定、统一的模型调用层至关重要…...

企业如何利用Taotoken实现多模型API的统一管理与访问控制

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 企业如何利用Taotoken实现多模型API的统一管理与访问控制 在AI应用开发实践中,一个常见且棘手的问题是模型API的管理。…...

GetQzonehistory:如何永久保存你的QQ空间记忆

GetQzonehistory:如何永久保存你的QQ空间记忆 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾在深夜翻看QQ空间,突然发现那些记录着青春点滴的说说正在逐…...

避坑指南:在Windows 11用DOSBox运行老游戏和工具,这些配置细节别忽略

Windows 11怀旧指南:DOSBox经典游戏完美运行配置手册 在数字时代快速迭代的浪潮中,那些承载着无数人青春记忆的DOS经典游戏——《仙剑奇侠传》《金庸群侠传》《大富翁》系列,依然让老玩家们念念不忘。Windows 11作为微软最新的操作系统&#…...

告别笔记本续航焦虑:手把手教你用NVMe电源管理给SSD“降频省电”

告别笔记本续航焦虑:手把手教你用NVMe电源管理给SSD“降频省电”每次带着笔记本出差,最担心的就是电量撑不过一场会议。你可能已经关闭了背光键盘、调低了屏幕亮度,甚至忍痛停用了独显,但续航依然捉襟见肘。其实,有一个…...

基于决策树与Boosting的暗网流量多阶段分类系统设计与实践

1. 项目概述:为什么暗网流量分类是个“硬骨头”?在网络安全这个没有硝烟的战场上,流量分类技术就像是前沿阵地的“雷达”和“声呐”。它的任务很简单:从海量、混杂的网络数据流中,快速、准确地识别出哪些是正常的网页浏…...

漏洞研究工作流:从CVE追踪到实战提升的闭环方法论

1. 这不是“资源列表”,而是一套可落地的漏洞研究工作流很多人一看到“在线资源全攻略”就下意识点开收藏,然后扔进浏览器书签夹吃灰。我见过太多安全从业者——包括刚入行的蓝队新人、想补实战短板的渗透测试员、甚至部分做红队支撑的工程师——把CVE编…...

医疗AI模型窃取攻击:原理、风险与超声影像场景的防御实践

1. 项目概述:当医疗AI的“大脑”面临被“复制”的风险在医疗影像领域,尤其是超声诊断,深度学习模型正以前所未有的速度改变着临床实践。它能从看似杂乱的超声回波信号中,精准地量化肝脏脂肪含量、鉴别乳腺肿物的良恶性&#xff0c…...

喜马拉雅xm-sign v3算法逆向解析与Node.js本地生成

1. 这不是“爬虫教程”,而是一次对前端签名机制的解剖式复现你有没有遇到过这样的情况:抓包看到喜马拉雅App或网页端发起的请求里,总带着一个叫xm-sign的参数,长度固定32位,每次请求都变,但又不是纯随机——…...

喷注重组方案对比:E-scheme与WTA在抗污染与子结构分析中的应用

1. 喷注重组方案:从基础概念到核心原理在粒子物理的高能对撞实验中,比如大型强子对撞机(LHC),我们探测到的最终产物是成千上万个带电和中性粒子。为了理解这些看似混乱的粒子流背后隐藏的物理过程——比如一个高能夸克…...

别再交智商税了!实测告诉你:用AI写论文,哪款软件控制重复率和AI率效果最好?

眼下毕业生和科研工作者的焦虑点很集中:论文查重率好不容易过关,AIGC疑似率却频频爆红;花了大把时间手动改写降AI痕迹,重复率又反弹回来。想靠普通工具同时守住查重和AI两道防线,根本就是天方夜谭。 事实上通用模型AI…...

Android App原生指令通道doCommandNative深度解析与Frida Hook实战

1. 这不是“逆向教程”,而是一次真实App通信链路的解剖现场你有没有遇到过这样的情况:在某A系头部电商App里,点击一个商品卡片,页面秒开;但用常规WebView调试或抓包工具去观察,却看不到任何明显的HTTP请求发…...

如何用Python快速接入Taotoken并调用多模型API构建智能客服系统

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 如何用Python快速接入Taotoken并调用多模型API构建智能客服系统 为你的CRM网站或内部系统集成智能对话能力,可以显著提…...

在 Taotoken 控制台中如何进行 API Key 的创建权限管理与操作审计

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在 Taotoken 控制台中如何进行 API Key 的创建权限管理与操作审计 对于需要将大模型能力集成到多个应用或分配给不同团队成员的开发…...

别再乱改sshd_config主文件了!Ubuntu 22.04下用sshd_config.d目录的正确姿势

Ubuntu 22.04下SSH配置管理的现代实践:告别直接修改sshd_config的时代 在Linux系统管理中,SSH服务的配置一直是个看似简单实则暗藏玄机的领域。许多管理员至今仍保持着直接修改 /etc/ssh/sshd_config 文件的习惯,却不知道Ubuntu等现代Linux…...

多版本滤波算法对比试验

一、设计版本V1.0资源二、设计版本V2.0资源和仿真三、设计版本V3.0资源和仿真四、设计优化V4.0设计优化V4.0是在V3.0基础上将inline off去掉后,资源立马下降。总结:V1.0版本,很奇怪,按道理,资源要多些,但是…...

摒弃传统持卡定位弊端 全方位筑牢井下应急安全屏障

摒弃传统持卡定位弊端 全方位筑牢井下应急安全屏障井下人员定位是矿山安全生产、应急救援、风险管控的核心基础支撑,直接关乎井下作业人员生命安全与矿山安全生产大局。长期以来,传统井下持卡定位模式凭借基础管控作用被广泛应用,但在深井开采…...

谷歌内部CSR策划SOP首次流出(非公开版):含风险预判矩阵、利益相关方触达热力图与监管审计应答话术库

更多请点击: https://codechina.net 第一章:Gemini CSR活动策划的底层逻辑与战略定位 Gemini CSR(Corporate Social Responsibility)活动并非孤立的品牌传播动作,而是深度嵌入企业技术价值观与长期可持续发展框架的战…...

3分钟快速上手:通达信缠论可视化插件终极使用指南

3分钟快速上手:通达信缠论可视化插件终极使用指南 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 通达信缠论可视化插件是一款专为股票投资者设计的缠论技术分析工具,能够将复杂的…...

C# MQTT性能优化:工业级高可靠低带宽实战指南

上个月给某汽车零部件厂做产线改造,差点栽在MQTT上。 现场环境你懂的,几百个传感器同时发数据,带宽只有可怜的2Mbps,还时不时断网。一开始用的是网上随便找的MQTT客户端代码,结果上线第一天就炸了。 消息延迟最高到了3…...

GORM 标签详解(数据库字段映射核心)

很多人刚学 GORM: 会觉得: gorm:"primaryKey" gorm:"index" gorm:"not null"这些东西: 像“魔法字符串”。 其实: 它本质上是在告诉 GORM: 数据库这一列应该怎么创建也就是:…...