DAY17|二叉树Part03|LeetCode: 530.二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、236.二叉树的最近公共祖先

目录

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

基本思路

有序数组法

C++代码

双指针法

C++代码

LeetCode: 501. 二叉搜索树中的众数

哈希法

C++代码

双指针法

C++代码

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

基本思路

C++代码


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

力扣代码链接

l文字讲解:LeetCode: 530.二叉搜索树的最小绝对差

视频讲解:二叉搜索树中,需要掌握如何双指针遍历!

基本思路

        题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。因为是有序二叉树,将所有二叉树的节点按照中序遍历,实际上可以看做是一个有序数组。这样任意两个不同节点值之间的最小差值不就一定产生在相邻的两个节点之间。

有序数组法

        这个题目存在两种解法。第一种解法是最容易想到的,就是将二叉树转换成有序数组,然后在遍历一遍数组,这样就可以找到最小绝对差了。

C++代码

class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {if (root == NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索树转换为有序数组traversal(root->right);
}
public:int getMinimumDifference(TreeNode* root) {vec.clear();traversal(root);if (vec.size() < 2) return 0;int result = INT_MAX;for (int i = 1; i < vec.size(); i++) { // 统计有序数组的最小差值result = min(result, vec[i] - vec[i-1]);}return result;}
};

双指针法

        另外一种方法就是在对搜索二叉树做中序遍历的时候就可以进行计算,我们可以考虑使用双指针法,这样就可以不构建数组便可以得到结果了,但是我们如何利用双指针求解呢?

  • 定义全局变量

        result:用来记录搜索二叉树任意两个节点的最小值,初试值设为INT_MAX。

        pre:pre指针需要事先定义好,否则在迭代中不就乱套了?

int result = INT_MAX;
TreeNode* pre = NULL;
  • 确定函数参数和返回值

        参数:传入当前遍历的节点指针。

        返回值:返回值应该为void,因为已经存在全局变量result对结果进行记录了。

void traversal(TreeNode* cur)
  • 确定终止条件

        如果当前节点为空,则停止。

if (cur == NULL) return;
  • 确定单层递归逻辑

        按照中序遍历的顺序,这里逻辑很神奇,一定要弄明白,可以试着自己模拟写一下过程。

traversal(cur->lfet); //左
if (pre != NULL)result = min(result, cur->val - pre->val); //中
//pre指向上一个节点!
pre = cur;
traversal(cur->right); //右

C++代码

class Solution {
private:
int result = INT_MAX;
TreeNode* pre = NULL;
void traversal(TreeNode* cur) {if (cur == NULL) return;traversal(cur->left);   // 左if (pre != NULL){       // 中result = min(result, cur->val - pre->val);}pre = cur; // 记录前一个traversal(cur->right);  // 右
}
public:int getMinimumDifference(TreeNode* root) {traversal(root);return result;}
};

LeetCode: 501. 二叉搜索树中的众数

力扣代码链接

文字讲解:LeetCode: 501. 二叉搜索树中的众数

视频讲解:不仅双指针,还有代码技巧可以惊艳到你!

哈希法

        这个题目,可以看做是普通二叉树和搜索二叉树来进行求解,对于一颗普通二叉树来讲,如果我们想要统计二叉树中的众数,最容易想到的就是使用哈希表来统计每个数出现的频率,使用map进行统计。

//用前中后序哪种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行
// map<int, int> key:元素,value:出现频率
void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历if (cur == NULL) return ;map[cur->val]++; // 统计元素频率searchBST(cur->left, map);searchBST(cur->right, map);return ;
}

        不过需要注意的是,C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。所以要把map转化数组即vector,再进行排序。

bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {return a.second > b.second; // 按照频率从大到小排序
}vector<pair<int, int>> vec(map.begin(), map.end());
sort(vec.begin(), vec.end(), cmp); // 给频率排个序

        前面已经对数组中的元素出现频率进行排序,只需要把出现频率最高的元素取出即可。

result.push_back(vec[0].first);
for (int i = 1; i < vec.size(); i++) {// 取最高的放到result数组中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;
}
return result;

C++代码

class Solution {
private:void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历if (cur == NULL) return ;map[cur->val]++; // 统计元素频率searchBST(cur->left, map);searchBST(cur->right, map);return ;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {return a.second > b.second;
}
public:vector<int> findMode(TreeNode* root) {unordered_map<int, int> map; // key:元素,value:出现频率vector<int> result;if (root == NULL) return result;searchBST(root, map);vector<pair<int, int>> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp); // 给频率排个序result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {// 取最高的放到result数组中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;}
};

双指针法

        这个题目依旧可以使用双指针法进行求解,不过前提是这个题目声明是搜索二叉树,并且我们必须使用中序遍历,因为只有遍历二叉树才是有序的。那么我们应该如何求出二叉树中的众数呢?

  • 定义全局变量

        pre:记录当前节点的上一个节点

        maxCount:用来记录元素出现的最大频率

        count:用来记录元素出现的频率

        result:用来记录结果

TreeNode* pre = NULL;
int count = 0;
int maxCount = 0;
vector<int> result;
  • 确定函数参数和返回值

        参数:传入一个指针,指向当前遍历的根节点

        返回值:因为结果已经在result中记录,因此不需要返回值。

void traversal(TreeNode* cur)
  • 确定终止条件

        当cur为空值时,停止遍历。

if (cur == NULL) return;
  • 确定单层递归逻辑
//左
traversal(cur->left);//中
if (pre == NULL) count = 1; //表示刚开始进行遍历,当前元素出现的频率为1
else if (pre->val == cur->val) count++; //如果前一个节点的值和当前节点的值相同,这频率加1
else count = 1;如果两个节点的值不相等,这更新频率
pre = cur; //让pre跟在cur的后面if (count == maxCount) result.push_back(cur->val);//如果当前元素出现的频率和最大频率相等,则说明这个数也是前面子集中的众数并进行记录//不得不说点睛之笔
if (count > maxCount){ maxCount = count;//表明出现了更大频率的元素,更新maxCount,并清空结果集result.clear();result.push_back(cur->val);//右
traversal(cur->right);
return;

C++代码

class Solution {
private:TreeNode* pre = NULL;int count = 0;int maxCount = 0;vector<int> result;void traversal(TreeNode* cur){if (cur == NULL) return ;//左traversal(cur->left);//中if (pre == NULL) count = 1; //表示刚开始进行遍历,当前元素出现的频率为1else if (pre->val == cur->val) count++; //如果前一个节点的值和当前节点的值相同,这频率加1else count = 1;//如果两个节点的值不相等,这更新频率pre = cur; //让pre跟在cur的后面if (count == maxCount) result.push_back(cur->val);//如果当前元素出现的频率和最大频率相等,则说明这个数也是前面子集中的众数并进行记录//不得不说点睛之笔if (count > maxCount){ maxCount = count;//表明出现了更大频率的元素,更新maxCount,并清空结果集result.clear();result.push_back(cur->val);}//右traversal(cur->right);return;}
public:vector<int> findMode(TreeNode* root) {traversal(root);return result;}
};

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

力扣代码链接

文字讲解:LeetCode: 236.二叉树的最近公共祖先

视频讲解:自底向上查找,有点难度!

基本思路

        对于二叉树我们大多是从上往下遍历,但是这个题目显然需要我们从下往上进行遍历,这个时候我们就应该想到需要利用回溯的方法进行求解,而后续遍历是天然的回溯过程,他先遍历左右孩子,然后根据左右孩子的值来处理中间节点。那么我们应该如何判断节点p和节点q的公共祖先是哪一个呢?有两种情况:

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

        情况二:很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q(p)。

        其实情况一和情况二代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本身就是 公共祖先的情况。

  • 确定函数参数和返回值

        参数:需要传入一个指向当前节点的指针,并且传入需要寻找的两个指向p和q节点的指针。

        返回值:返回一个指向两个节点公共祖先的指针。

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
  • 确定终止条件

        遍历整个二叉树,当节点为空时,表示当前未找到目标节点,则返回null,如果节点为p或q,则表明找到了,返回当前节点

if(root == p || root == q) return root;
if(root == NULL) return NULL;
  • 确定单层递归逻辑

        如果左子树存在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 retuen NULL; //  (left == NULL && right == NULL)

C++代码

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if (root == q || root == p || root == NULL) 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  { //  (left == NULL && right == NULL)return NULL;}}
};

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

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

相关文章

「Mac畅玩鸿蒙与硬件27」UI互动应用篇4 - 猫与灯的互动应用

本篇将带领你实现一个趣味十足的互动应用&#xff0c;用户点击按钮时猫会在一排灯之间移动&#xff0c;猫所在的位置灯会亮起&#xff08;on&#xff09;&#xff0c;其余灯会熄灭&#xff08;off&#xff09;。应用会根据用户的操作动态更新灯光状态和文本提示当前亮灯的位置&…

【网络】套接字编程——UDP通信

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;UDP网络服务器简单模拟实现。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;…

黑马官网2024最新前端就业课V8.5笔记---HTML篇

Html 定义 HTML 超文本标记语言——HyperText Markup Language。 标签语法 标签成对出现&#xff0c;中间包裹内容<>里面放英文字母&#xff08;标签名&#xff09;结束标签比开始标签多 /拓展 &#xff1a; 双标签&#xff1a;成对出现的标签 单标签&#xff1a;只有开…

openfoam中生成的3d案例提取得到slice后的2d案例

问题&#xff1a; 由于前期准备做3d的案例&#xff0c;并且模拟也比较费时间&#xff0c;现在生成了几十份3d的数据&#xff0c;但是现在只想要2d的数据来演示&#xff0c;该如何提取或者转换呢&#xff1f; 解决方法&#xff1a; 1.说明图片中的每个2d视图的points都是恒定不…

使用 Sortable.js 库 实现 Vue3 elementPlus 的 el-table 拖拽排序

文章目录 实现效果Sortable.js介绍下载依赖添加类名导入sortablejs初始化拖拽实例拖拽完成后的处理总结 在开发过程中&#xff0c;我们经常需要处理表格数据&#xff0c;并为用户提供便捷的排序方式。特别是在需要管理长列表、分类数据或动态内容时&#xff0c;拖拽排序功能显得…

STM32 + CubeMX + 硬件SPI + W5500 +UDP

这篇文章记录一下STM32W5500UDP的调试过程&#xff0c;实现UDP数据的接收与发送。 目录 一、W5500模块介绍二、Stm32CubeMx配置三、Keil代码编写1、添加W5500驱动代码到工程&#xff08;添加方法不赘述&#xff0c;驱动代码可以在官网找&#xff09;2、在工程中增加代码&#…

2023年SCRM系统排名分析及市场趋势解读

内容概要 当前&#xff0c;SCRM&#xff08;社交客户关系管理&#xff09;系统在企业运营中的重要性日益凸显&#xff0c;尤其是在快速发展的数字经济环境中。2023年的SCRM市场展现出多元化与专业化的趋势&#xff0c;不同企业在客户关系管理方面的需求各有不同&#xff0c;这…

StableDiffusion-3.5 文生图模型本地部署尝鲜

文章目录 官方仓库ComfyUI 配置模型文件生成图片&#xff0c;观察日志生成样例 买了新的 4070TiS 显卡之后&#xff0c;终于有了个人的 16GB 显存&#xff0c;再也不用在关键时刻和实验室的其他人抢那两张 3080Ti 12G 了&#xff0c;所以想试试看干净的 Linux 环境下&#xff0…

规范:项目、目录、文件、样式、事件、变量、方法、url参数、注释、git提交 命名规范及考证

一、规范命名的重要性 易懂、通用、规范、标准、专业性、是经验积累的体现 1.1、常见命名方法 序号命名方法解释1全小写2全大写3驼峰&#xff1a;小驼峰命名法4驼峰&#xff1a;大驼峰命名法5烤串命名法 / 脊柱命名法6下划线分隔法 二、项目名 采用小写字母和中划线&#…

Navicat 连接远程腾讯云服务器的MySQL数据库

首先需要开放开放腾讯云安全端口&#xff0c;可以参考这个链接腾讯云服务器入站规则端口开放使用指南(CentOS系统)。 但是注意需要开放的是IPv6&#xff0c;这个可以通过netstat命令查看确认。 然后查看当前用户信息 select user, host from mysql.user一般看到的都是 localh…

第三十四篇:URL和URI的区别,HTTP系列一

前面我们讲到通过TCP协议通信双方建立可靠连接&#xff0c;那么此时双方进行通信&#xff0c;需要用人能理解的形式进行信息组织&#xff0c;也就是为各种特定需求服务&#xff0c;满足日常生活中的各种场景。 比如&#xff1a;网页浏览、电子邮件、远程登录、文件传输、网络管…

什么情况下,不推荐建立索引?

一般有以下几种情况不推荐建立索引&#xff1a; 1&#xff09;对于数据量很小的表 当表的数据量很小&#xff08;如几百条记录&#xff09;时&#xff0c;建立索引并不会显著提高查询性能&#xff0c;反而可能增加管理的复杂性&#xff1b; 2&#xff09;频繁更新的表 对于…

GitHub上传自己的项目

目录 一、安装Git插件 1&#xff09;下载 2&#xff09;安装 二、创建Gothub的创库 三、通过Git上传本地文件到Github 四、其他 1、部分指令 2、如果已经运行过git init并设置了[user]&#xff0c;下次可以直接用 一、安装Git插件 1&#xff09;下载 下载地址&#x…

「Mac畅玩鸿蒙与硬件26」UI互动应用篇3 - 倒计时和提醒功能实现

本篇将带领你实现一个倒计时和提醒功能的应用&#xff0c;用户可以设置倒计时时间并开始计时。当倒计时结束时&#xff0c;应用会显示提醒。该项目涉及时间控制、状态管理和用户交互&#xff0c;是学习鸿蒙应用开发的绝佳实践项目。 关键词 UI互动应用倒计时器状态管理用户交互…

Linux动态库和静态库

1&#xff0c;手动制作静态库 1&#xff0c;如何形成静态库文件 做库时&#xff0c;头文件(.h)必须暴露&#xff0c;源文件(.c)必须隐藏。 操作&#xff1a;将需要形成库的文件编译成.o文件&#xff1a; 然后用指令&#xff1a;ar -rc libmy_stdio.a my_stdio.o my_string.o…

java基础之 String\StringBuffer\ StringBuilder

文章目录 String字符串的创建为什么说String是不可变的&#xff1f;创建后的字符串存储在哪里&#xff1f;字符串的拼接String类的常用方法 StringBuilder & StringBuffer使用方法验证StringBuffer和StringBuilder的线程安全问题 总结三者区别什么情况下用运算符进行字符串…

告别繁琐统计,一键掌握微信数据

微信数据管理的挑战在数字时代&#xff0c;微信已成为我们日常沟通和商业活动的重要工具。然而&#xff0c;随着微信号数量的增加&#xff0c;手动统计每个账号的数据变得越来越繁琐。从好友数量到会话记录&#xff0c;再到转账和红包&#xff0c;每一项都需要耗费大量的时间和…

bert-base-chinese模型使用教程

向量编码和向量相似度展示 import torch from transformers import BertTokenizer, BertModel import numpy as npmodel_name "C:/Users/Administrator.DESKTOP-TPJL4TC/.cache/modelscope/hub/tiansz/bert-base-chinese"sentences [春眠不觉晓, 大梦谁先觉, 浓睡…

HTML+CSS科技感时钟(附源码!!!)

预览效果 源码(直接复制使用) <!DOCTYPE html> <html lang"zh-Hans"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>科技感时钟</…

PyQt5实战——UTF-8编码器功能的实现(六)

个人博客&#xff1a;苏三有春的博客 系类往期文章&#xff1a; PyQt5实战——多脚本集合包&#xff0c;前言与环境配置&#xff08;一&#xff09; PyQt5实战——多脚本集合包&#xff0c;UI以及工程布局&#xff08;二&#xff09; PyQt5实战——多脚本集合包&#xff0c;程序…