代码随想录刷题笔记 DAY 21 | 二叉搜索树的最小绝对值差值 No.530 | 二叉搜索树中的众数 No.501 | 二叉树的最近公共祖先 No.236

Day 21

01. 二叉搜索树的最小绝对值差值(No. 530)

题目链接

代码随想录题解

1.1 题目

给你一个二叉搜索树的根节点 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 笔记

提到二叉搜索树其解题最重要的特质就是:

中序遍历的时候输出是一个有序的序列

那本题中的问题就比较简单了,转化为一个 有序序列 的差的绝对值的最小值,这个最小值一定是 出现在相邻的位置,因为前一个减去后一个的绝对值肯定不可能小于前一个减去后面其他的值。

先思考如何在数组中实现这个算法,再将其转化为二叉树递归的写法:

因为要同时操作两个数,所以需要一个指针指向前一个值,很容易可以写出代码:

public static void getMin(int[] arr) {int pre = -1; // 指针,指向前一个值int res = Integer.MAX_VALUE;for (int i : arr) {if (pre == -1) {i = pre; // 为 pre 初始化} else {res = Math.min(res, i - pre);pre = i;}}	
}

这样不断遍历直到结束就能得到查的最小绝对值。

接下来就是将其改为二叉树的写法,已知中序遍历得到的结果其实就是该数组,所以将上面的步骤直接搬到中序位置即可。

1.3 代码
class Solution {int pre;int ans;public int getMinimumDifference(TreeNode root) {pre = -1;ans = Integer.MAX_VALUE;reverse(root);return ans;}public void reverse(TreeNode node) {if (node == null) {return;}reverse(node.left);if (pre == -1) {pre = node.val;} else {ans = Math.min(ans, node.val - pre);pre = node.val;}reverse(node.right);}
}

02. 二叉搜索树中的众数(No. 501)

题目链接

代码随想录题解

2.1 题目

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

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

假定 BST 满足如下定义:

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

示例 1:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

示例 2:

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

提示:

  • 树中节点的数目在范围 [1, 104]
  • -105 <= Node.val <= 105
2.2 笔记

还是和上面相同,对于二叉搜索树优先考虑对数组的操作,然后将这个操作转换到二叉树的中序遍历即可。

对于一个有序数组要求众数的话,首先需要一个指针指向前一个数,还需要一个 tempNum 来统计当前的总数和一个 maxNum 来统计总的数目,当
current == pre 的时候就让 tempNum++,且当 current != pre 的时候说明已经到了不同的数字,再去统计 tempNummaxNum 哪个大,持续遍历更新直到遍历结束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

直接写出代码

maxNum = 0;
tempNum = 0;
List<Integer> res = new ArrayList<>();
pre = Integer.MAX_VALUE;for (int current : arr) {if (pre == Integer.MAX_VALUE || current != pre) {tempNum = 1;pre = current;} else {tempNum++;}if (tempNum > maxNum) {res.clear();res.add(node.val);maxNum = tempNum;} else if (tempNum == maxNum) {res.add(node.val);}
}

注意当 tempNum > maxNum 的时候说明此时 res 中存储的内容已经不是最大的了,这时候就需要 res.clear() 来清除内部的值再来添加。

最后将这段代码转移到中序遍历中即可。

2.3 代码
class Solution {int pre = Integer.MAX_VALUE; // 前一个节点的值List<Integer> res = new ArrayList<>(); // 结果集int maxNum; //最大值int tempNum; // 当前节点的总数public int[] findMode(TreeNode root) {maxNum = 0;tempNum = 0;reverse(root);int[] resArr = new int[res.size()];for (int i = 0; i < res.size(); i++) {resArr[i] = res.get(i);}return resArr;}public void reverse(TreeNode node) {if (node == null) {return;}reverse(node.left);// 计数if (pre == Integer.MAX_VALUE || node.val != pre) {tempNum = 1;pre = node.val;} else {tempNum++;}// 判断if (tempNum > maxNum) {res.clear();res.add(node.val);maxNum = tempNum;} else if (tempNum == maxNum) {res.add(node.val);}reverse(node.right);}
}

03. 二叉树的最近公共祖先(No. 236)

题目链接

代码随想录题解

3.1 题目

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

百度百科中最近公共祖先的定义为:“对于有根树 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
  • pq 均存在于给定的二叉树中。
3.2 笔记

要找到最近的公共祖先,首先想到的思路是这样的:

先找到 p 点或者 q 点,不断向上返回,直到双方的遍历的节点重合,则就说明找到了最近的公共祖先。

两边节点重合就代表着:

这个节点的左子树含有 p 或者 q 其中之一,右子树含有 p 或者 q 其中之一

能够得出这个结论是因为题目中要求的 最近,如果这个节点的左子树或者右子树包含 p 和 q 那它一定不是最近的公共祖先,且题目中提到每个节点的 val 不重复,且一定会包含 p 和 q,由此推断出如上的结论。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以通过 Boolean 来判断是否含有,然后在 left == true && right == true 的时候读取这个节点然后返回;比如上图中,遍历到 2 的时候发现其左子树和右子树不分别包含 p q,说明 2 不是需要的节点,当遍历到 5 的时候,发现其 左子树和右子树分别包含 p 和 q 所以返回 5,需要注意的是针对与题目中的实例 2 ,也就是 p 或者 q 就是它们的公共祖先的情况要做额外的处理。

这里因为题目中要求的是返回 TreeNode 所以这里将返回值设为 TreeNode,返回值设定为 p 和 q 的公共祖先,以 left 和 right 是否为空作为判断依据来判断是否左子树和右子树同时包含:

    if (node == null) {return null;}if (node.val == pVal || node.val == qVal) {return node;}TreeNode left = reverse(node.left);TreeNode right = reverse(node.right);// 判断逻辑

if (left != null && right != null) 说明此时是需要的节点,其判断方法和上面的思想是完全相同的。

但好处是不需要处理 p 或者 q 就是它们的公共祖先的情况

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因为上面的代码当遇到 q = 2 的时候就通过
if (node.val == pVal || node.val == qVal) {return node;} 来直接返回了,这样直到顶上返回的值都是 2

而如果采用刚刚的情况就需要再多加一步来判断这个情况

3.3 代码
class Solution {int pVal;int qVal;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {pVal = p.val;qVal = q.val;return reverse(root);}public TreeNode reverse(TreeNode node) {if (node == null) {return null;}if (node.val == pVal || node.val == qVal) {return node;}TreeNode left = reverse(node.left);TreeNode right = reverse(node.right);if (left != null && right != null) {return node;} else if (left == null && right != null) {return right;} else if (left != null && right == null) {return left;} else {return null;}}
}

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

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

相关文章

Caffeine史上最快的内存缓存

引言 在现代的Web应用程序中&#xff0c;缓存是提升性能&#xff0c;减少数据库负载&#xff0c;加快响应速度的关键技术之一。Spring Boot作为一个简化Spring应用开发的框架&#xff0c;提供了与多种缓存技术集成的支持。Caffeine是一个高性能&#xff0c;灵活的缓存库&#…

Transformer 自然语言处理(三)

原文&#xff1a;Natural Language Processing with Transformers 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第八章&#xff1a;使 transformers 在生产中更高效 在之前的章节中&#xff0c;您已经看到了 transformers 如何被微调以在各种任务上产生出色的结果。…

C++STL之容器

STL的概述 STL(Standard Template Library,标准模板库) STL的6大组件&#xff1a;容器、算法、迭代器、适配器、仿函数、空间配置 容器&#xff1a;存放数据 算法&#xff1a;操作数据 迭代器&#xff1a;算法 通过迭代器 操作 容器 适配器&#xff1a;为算法 提供更多的接口 …

SQL报错注入

SQL注入报错注入 报错注入原理:报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的在遇到有报错回显的时候&#xff0c;但是没有数据回显的情况下可以利用报错注入的函数: 1.floor():向下取整 2.extractvalue(): 对XML文档进行查询的函数&#xff0c;当参数的格式…

202416读书笔记|《总有人会拥抱满身带刺的你》——今天我请客,想请你快乐

202416读书笔记|《总有人会拥抱满身带刺的你》——今天我请客&#xff0c;想请你快乐 这是一篇暖萌轻松的绘本推荐记录书评&#xff0c;《总有人会拥抱满身带刺的你》纳米著&#xff0c;《今天我请客&#xff0c;想请你快乐》燕七著&#xff0c;都还不错&#xff0c;截取摘录了…

C++-模板基础

1. 泛型编程 大家在学习过程中一定写过swap函数吧&#xff0c;那么swap函数的可以写成很多种形式&#xff0c;因为形参的类型可以是任意类型&#xff0c;那么我们如果想用多种swap函数的话&#xff0c;就意味着我们必须写多个swap函数吗&#xff1f;不是的&#xff0c;C为了解…

Web项目利用OSS进行图像存储服务

一、OSS介绍 在Web项目中&#xff0c;一些常见的功能&#xff0c;比如展示图片&#xff0c;修改头像等&#xff0c;都需要进行图片的上传操作&#xff0c;但是如果是存储在Web服务器中&#xff0c;在读取图片的时候会占用比较多的资源&#xff0c;影响服务器的性能。 常…

Node需要了解的知识

Node能执行javascript的原因。 浏览器之所以能执行Javascript代码&#xff0c;因为内部含有v8引擎。Node.js基于v8引擎封装&#xff0c;因此可以执行javascript代码。Node.js环境没有DOM和BOM。DOM能访问HTML所有的节点对象&#xff0c;BOM是浏览器对象。但是node中提供了cons…

音箱、功放播放HDMI音频解决方案之HDMI音频分离器HHA

HDMI音频分离器HHA简介 HDMI音频分离器HHA具有一路HDMI信号输入&#xff0c;转换成一路HDMI信号、一路5.1光纤音频信号、一路5.1 SPDIF/同轴音频信号和一路模拟左右声道立体声信号输出&#xff0c;同时还支持EDID存储及兼容HDCP功能&#xff1b;分辨率最高支持1920*1080p&#…

Ainx框架实现 一

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于Ainx系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列…

QGraphicsScene中显示GIF动图,GIF图片在场景中移动

文章目录 效果图引言显示GIF图片&#xff08;方法一&#xff09;显示GIF图片&#xff08;方法二&#xff09;GIF图片在场景中运动 效果图 引言 当我们想在QGraphicsScene显示或者说绘制一张GIF动图时&#xff0c;该如何处理&#xff1f;Qt中的 QGraphicsItem 的 paint 函数中&…

【开源】WordPress一键崩溃宕机插件(整活娱乐)

插件介绍 可一键实现Wordpress崩溃宕机的整活向插件&#xff08;请勿用于非法途径&#xff0c;仅供整活娱乐&#xff09;。鼓励关注网站性能的提升&#xff0c;以提供更好的用户体验&#xff0c;提倡为用户提供良好体验和高效速度的原则。 介绍 长期以来&#xff0c;人们都在…