LeetCode 530 二叉搜索树的最小绝对差

题目链接:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:


输入:root = [4,2,6,1,3]
输出:1
示例 2:


输入:root = [1,0,48,null,null,12,49]
输出:1

 首先将二叉搜索树中序遍历转化为有序数组,其实在遍历的过程中就可以直接计算了。

需要用一个pre节点来记录当前节点的前一个节点。

递归法:

class Solution {int res=Integer.MAX_VALUE;TreeNode pre=null;public int getMinimumDifference(TreeNode root) {//递归if(root==null)return 0;getMinimumDifference(root.left);if(pre!=null)res=Math.min(res,root.val-pre.val);pre=root;getMinimumDifference(root.right);return res;}
}

迭代法:

class Solution {public int getMinimumDifference(TreeNode root) {//迭代int res=Integer.MAX_VALUE;TreeNode pre=null;Stack<TreeNode> st=new Stack<>();st.push(root);while(!st.isEmpty()){TreeNode node=st.pop();if(node!=null){if(node.right!=null)st.push(node.right);st.push(node);st.push(null);if(node.left!=null)st.push(node.left);}else{TreeNode tmp=st.pop();if(pre!=null)res=Math.min(res,tmp.val-pre.val);pre=tmp;}}return res;}
}

LeetCode 501 二叉搜索树中的众数

题目链接:501. 二叉搜索树中的众数 - 力扣(LeetCode)

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树

示例 1:


输入:root = [1,null,2,2]
输出:[2]
示例 2:

输入:root = [0]
输出:[0]

 最直观的方法就是把整个树遍历了,用map统计频率,把频率排序,最后取前面高频的元素的集合。

class Solution {public int[] findMode(TreeNode root) {Map<Integer,Integer> map=new HashMap<>();Stack<TreeNode> st=new Stack<>();if(root!=null)st.push(root);while(!st.isEmpty()){TreeNode node=st.pop();if(node!=null){if(node.right!=null)st.push(node.right);st.push(node);st.push(null);if(node.left!=null)st.push(node.left);}else{node=st.pop();if(!map.containsKey(node.val))map.put(node.val,0);else map.put(node.val,map.get(node.val)+1);}}int maxCount=0;List<Integer> list=new ArrayList<>();for(Integer obj:map.keySet()){if(map.get(obj)>maxCount)maxCount=map.get(obj);}for(Integer obj:map.keySet()){if(map.get(obj)==maxCount)list.add(obj);}int res[]=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

但既然是二叉搜索树,它中序遍历就是有序的,遍历有序数组的元素出现频率,从头遍历,那么一定是两个相邻元素作比较,然后把出现频率最高的元素输出就行了。

需要定义一个pre节点,是当前节点的前一个节点,每次将二者作比较。

if(pre==null)count=1;
else if(pre!=null&&tmp.val==pre.val)count++;
else count=1;
pre=tmp;

因为可能有多个众数,所以应该要先遍历一遍数组,找出最大频率,然后再遍历一遍数组把出现频率为该最大频率的元素放入结果中。这样的方式需要遍历两次数组。

那如何只遍历一遍呢?

如果当前元素出现频率等于最大频率,就把这个元素加入到结果集中;如果当前元素出现频率大于最大频率,先更新最大频率,然后清空结果集,因为结果集之前的元素都失效了,然后再把当前元素加入结果集中。

完整代码如下:

class Solution {public int[] findMode(TreeNode root) {int count=0;int maxCount=0;Stack<TreeNode> st=new Stack<>();List<Integer> list=new ArrayList<>();TreeNode pre=null;if(root!=null)st.push(root);while(!st.isEmpty()){TreeNode node=st.pop();if(node!=null){if(node.right!=null)st.push(node.right);st.push(node);st.push(null);if(node.left!=null)st.push(node.left);}else{TreeNode tmp=st.pop();if(pre==null)count=1;else if(pre!=null&&tmp.val==pre.val)count++;else count=1;pre=tmp;if(count==maxCount)list.add(tmp.val);else if(count>maxCount){maxCount=count;list.clear();list.add(tmp.val);}}}int[] res=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

递归写法:

class Solution {List<Integer> list=new ArrayList<>();int count=0;int maxCount=0;TreeNode pre=null;public int[] findMode(TreeNode root) {//递归if(root==null)return null;findMode(root.left);if(pre==null)count=1;else if(pre!=null&&pre.val==root.val)count++;else count=1;pre=root;if(count==maxCount)list.add(root.val);else if(count>maxCount){maxCount=count;list.clear();list.add(root.val);}findMode(root.right);int[] res=new int[list.size()];for(int i=0;i<list.size();i++){res[i]=list.get(i);}return res;}
}

LeetCode 236 二叉树的最近公共祖先

题目链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:


输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:


输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:

输入:root = [1,2], p = 1, q = 2
输出:1

条件:

  • 树中节点数目在范围 [2, 105] 内。
  • -109 <= Node.val <= 109
  • 所有 Node.val 互不相同 。
  • p != q
  • p 和 q 均存在于给定的二叉树中。

 思路:首先想的是要是能自底向上查找就好了,这样就可以找到公共祖先了。

那么如何自底向上查找?

回溯法,后序遍历可以根据左右子树的返回值来处理中节点的逻辑。

如何判断一个节点是节点p和节点q的公共祖先?

如果找出一个节点,发现左子树出现节点p,右子树出现节点q,或者左子树出现节点q,右子树出现p,那么该节点就是节点p和q的最近公共祖先。

所以递归逻辑就是:如果递归遍历遇到q,就返回q;遇到p,就返回p,那么如果左右子树的返回值不为空,说明此时的中节点,一定是p和q的最近公共祖先。 

因为题目中说了二叉树节点是不重复的,所以不用担心会不会左子树和右子树都返回q或p这样的问题。

实现代码如下:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {//递归if(root==null||root==p||root==q)return root;TreeNode left=lowestCommonAncestor(root.left,p,q);TreeNode right=lowestCommonAncestor(root.right,p,q);if(left!=null&&right!=null)return root;else if(left==null&&right!=null)return right;else if(left!=null&&right==null)return left;else return null;}
}

如果left 和 right都不为空,说明此时root就是最近公共节点。这个比较好理解。

如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之亦然

为什么left为空,right不为空,目标节点就通过right返回?

我们来看下面的图:

节点为10的左子树返回null,右子树返回7,那么此时节点10就要把右子树的返回值返回上去。

完整流程图如下:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89122.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89122.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89122.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自增主键为什么不是连续的?

前言 如果一个线程回滚&#xff0c;例如唯一键冲突的情况回滚时&#xff0c;回滚了sql语句&#xff0c;但是并没有把自增的值也-1。那么就会导致下一条插入的数据自增id出现了跳跃。 自增主键为什么不是连续的&#xff1f;前言执行时机为什么自增主键不是连续的为什么不回滚自…

OpenCV图像基本操作:读取、显示与保存

在图像处理项目中&#xff0c;图像的 读取&#xff08;imread&#xff09;、显示&#xff08;imshow&#xff09; 和 保存&#xff08;imwrite&#xff09; 是最基础也是最常用的三个操作。本文将详细介绍这三个函数的功能、用法和注意事项&#xff0c;并提供一个完整示例供读者…

.NET控制台应用程序中防止程序立即退出

在VB.NET控制台应用程序中防止程序立即退出&#xff0c;主要有以下几种常用方法&#xff0c;根据需求选择适合的方案&#xff1a; 方法1&#xff1a;等待用户输入&#xff08;推荐&#xff09; Module Module1Sub Main()Console.WriteLine("程序开始运行...") 这里是…

Vue3 + Three.js 极速入门:打造你的第一个3D可视化项目

文章目录前言一、环境准备1.1 创建Vue3项目1.2 安装Three.js二、Three.js核心概念速览三、实战&#xff1a;创建旋转立方体3.1 组件化初始化四、核心代码解析4.1 Vue3响应式整合技巧4.2 性能优化要点五、进阶功能扩展5.1 数据驱动控制5.2 加载3D模型六、常见问题解决七、资源推…

【设计模式】享元模式(轻量级模式) 单纯享元模式和复合享元模式

享元模式&#xff08;Flyweight Pattern&#xff09;详解一、享元模式简介 享元模式&#xff08;Flyweight Pattern&#xff09; 是一种 结构型设计模式&#xff08;对象结构型模式&#xff09;&#xff0c;它通过共享技术实现相同或相似对象的重用&#xff0c;以减少内存占用和…

驱动开发_2.字符设备驱动

目录1. 什么是字符设备2. 设备号2.1 设备号概念2.2 通过设备号dev分别获取主、次设备号的宏函数2.3 主设备号的申请静态申请动态分配2.4 注销设备号3. 字符设备3.1 注册字符设备3.2 注销字符设备3.3 应用程序和驱动程序的关系3.4 file_opertaions结构体3.5 class_create3.6 创建…

直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡

直播推流技术底层逻辑详解与私有化实现方案-以rmtp rtc hls为例-优雅草卓伊凡由于我们的甲方客户要开始为我们项目产品上加入私有化的直播&#xff0c;这块不得不又捡起来曾经我们做直播推流的事情了&#xff0c;其实私有化直播一直并不是一件容易的事情&#xff0c;现在大部分…

一文读懂现代卷积神经网络—深度卷积神经网络(AlexNet)

目录 深度卷积神经网络&#xff08;AlexNet&#xff09;是什么&#xff1f; 一、AlexNet 的核心创新 1. 深度架构 2. ReLU 激活函数 3. 数据增强 4. Dropout 正则化 5. GPU 并行计算 6. 局部响应归一化&#xff08;LRN&#xff09; 二、AlexNet 的网络结构 三、AlexN…

JVM 垃圾收集算法全面解析

1. 引言1.1 为什么需要垃圾收集&#xff1f;在Java应用中&#xff0c;垃圾收集&#xff08;Garbage Collection&#xff0c;GC&#xff09;是一个至关重要的机制&#xff0c;它使得开发者不需要手动管理内存。与传统的语言&#xff08;如C或C&#xff09;不同&#xff0c;Java通…

Vmware中安装的CentOS7如何扩展硬盘大小

起初创建虚拟机时&#xff0c;大小设置不合理&#xff0c;导致我在尝试开源项目时空间不足重新扩展硬盘&#xff0c;不仅需要在虚拟机设置中配置&#xff0c;还需要在系统内重新进行分区一、虚拟机设置打开虚拟机设置→硬盘→扩展&#xff0c;将大小设置为自己期望的大小&#…

Python+MongoDB高效开发组合

如大家所知&#xff0c;Python与MongoDB的结合是一种高效的开发组合&#xff0c;主要用于通过Python进行数据存储、查询及管理&#xff0c;利用MongoDB的文档型数据库特性实现灵活的数据处理。下面让 Python 连接上 MongoDB&#xff1a;安装 PyMongo&#xff1a;pip3 install p…

【论文阅读】Masked Autoencoders Are Effective Tokenizers for Diffusion Models

introduce什么样的 latent 空间更适合用于扩散模型&#xff1f;作者发现&#xff1a;相比传统的 VAE&#xff0c;结构良好、判别性强的 latent 空间才是 diffusion 成功的关键。研究动机&#xff1a;什么才是“好的 latent 表征”&#xff1f;背景&#xff1a;Diffusion Models…

每日一SQL 【游戏玩法分析 IV】

文章目录问题案例执行顺序使用分组解决问题 案例 执行顺序 SQL 语句的执行顺序&#xff08;核心步骤&#xff09; 同一层级的select查询内部, 别名在整个 SELECT 计算完成前不生效 使用分组解决 select distinct s.product_id, Product.product_name from Sales sleft join …

内部文件审计:企业文件服务器审计对网络安全提升有哪些帮助?

企业文件服务器审计工作不仅对提升企业网络信息安全起到重要作用&#xff0c;还能对企业内部网络文件信息是否合规进行判断。因此企业文件服务器审计一直被高度重视。 一、文件服务器为何成为攻击焦点&#xff1f; 企业文件服务器通常集中存储财务报表、人事档案、研发资料、客…

FusionOne HCI 23 超融合实施手册(超聚变超融合)

产品介绍 FusionOne HCI作为实现企业信息一体化的IT基础设施平台&#xff0c;以“软硬件垂直深度集成和调优”、“快速部署”、“统一管理”的理念&#xff0c;提供应用融合部署&#xff0c;提升核心业务运作效率&#xff0c;降低整体采购成本。 FusionOne HCI代表了IT产品的…

AI算姻缘测算小工具流量主微信小程序开源

功能特点 响应式设计&#xff1a;完美适配各种移动设备屏幕尺寸 精美UI界面&#xff1a; 柔和的粉红色渐变背景 圆角卡片设计 精心设计的字体和间距 爱心图标点缀 动态效果&#xff1a; 点击按钮时的动画反馈 测算结果的平滑过渡动画 爱心漂浮动画 进度条动态填充 AI测算功能&a…

Vue获取上传Excel文件内容并展示在表格中

一、安装依赖 npm install xlsx 二、引用依赖 import XLSX from xlsx 三、代码实现 1、注意&#xff1a;函数 analysis 中reader.readAsBinaryString(file)&#xff0c;file的数据格式如图所示 2、示例代码 <!-- 项目使用的前端框架为非流行框架&#xff0c;主要关注…

pipelineJob和pipeline的关系

pipelineJob与pipeline在Jenkins体系中构成配置层与执行层的协同关系,具体关联如下: 一、核心功能定位 概念作用实现层级pipelineJob定义Job的元数据(如SCM配置、日志策略)配置层pipeline描述实际构建流程(如阶段划分、并行任务)执行层scriptPath桥梁作用:将配置层定义…

第二十篇 Word文档自动化:Python批量生成、模板填充与内容修改,告别繁琐排版!

python实现word 自动化重复性文档制作&#xff0c;手动填充模板&#xff0c;效率低下还易错1.python-docx入门&#xff1a;Word文档的“瑞士军刀”&#xff01;1.1 安装与基础概念&#xff1a;文档、段落、运行、表格1.2 打开/创建Word文档&#xff1a;Python与Word的初次接触1…

【C# in .NET】7. 探秘结构体:值类型的典型代表

探秘结构体&#xff1a;值类型的典型代表 在 C# 的类型系统中&#xff0c;结构体&#xff08;Struct&#xff09;作为值类型的典型代表&#xff0c;一直扮演着既基础又微妙的角色。许多开发者在日常编码中虽频繁使用结构体&#xff08;如int、DateTime等&#xff09;&#xff0…