代码随想录 | Day23 | 二叉树:二叉搜索树的最小绝对差二叉搜索树中的众数

news2024/9/24 20:21:11

代码随想录 | Day23 | 二叉树:二叉搜索树的最小绝对差&&二叉搜索树中的众数

主要学习内容:

1.二叉搜索树性质:中序遍历是递增的有序序列

2.自定义pair排序函数复习

3.双指针在二叉树中的应用(重点)

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

530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

解法:利用二叉搜索树性质进行中序遍历

**思路:**总的思路是二叉搜索树的中序遍历是一个递增的有序序列,可以把它看成一个数组。

那么就有了两个思路

1.把遍历的数全都存到一个数组中,然后循环,看相邻两个数的差的大小,记录最小值就是了

2.在遍历的过程中想办法把前一个结点的值给记下来,然后根据遍历顺序进行相减得到最后的结果。可以利用双指针来记录前一个节点

在这里介绍第二种

1.函数参数和返回值

int minVal=INT_MAX;
TreeNode *pre=nullptr;
void tra(TreeNode *t)

minVal记录答案

pre是慢指针,指向前一个遍历的结点,用来和当前结点t进行相减操作,慢指针初始化为空是因为我们并不知道有序序列第一个结点是哪个

本题无需返回值

2.终止条件

if(t==nullptr)
	return;

遇到空直接返回

3.本层代码逻辑

中序遍历。

需要注意的是慢指针的更新操作。

有两种情况,当我们没有找到有序序列第一个数时慢指针是空的,我们只有找到第一个数之后才能把慢指针更新,之后才能进行minVal的更新。

快慢指针的更新操作要在左中右的中,即本层。

tra(t->left);//左
//中
if(pre!=nullptr)
{
    //更新minval,即快指针减去慢指针的值
	if(t->val-pre->val<minVal)
	minVal=t->val-pre->val;
}
pre=t;//更新慢指针
//右
tra(t->right);

完整代码:

class Solution {
public:
    int minVal=INT_MAX;
    TreeNode *pre=nullptr;
    void tra(TreeNode *t)
    {   
        if(t==nullptr)
            return;
        tra(t->left);
        if(pre!=nullptr)
        {
            if(t->val-pre->val<minVal)
                minVal=t->val-pre->val;
        }
        pre=t;
        tra(t->right);
    }
    int getMinimumDifference(TreeNode* root) {
        tra(root);
        return minVal;
    }
};
//直接遍历代码
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;
    }
};

难点:1.想到用双指针记录

2.慢指针的更新操作

本次犯的错误:

想着记录minval时直接把两个数相减,但其实连t->val和val的前后关系都没弄对,传入根结点时,也不会知道前面的第一个结点的值到底是多少,最后也自然得不到结果,直接传值也没法像慢指针那样有nullptr作为标志,因为你设置的标志值可能就是第一个结点的值。

比如说

if(val!=0)
{
    更新minval
}
val=t->val;
但是0可能就是我们找的第一个结点的值。
错误示范:
	int minVal=INT_MAX;
    void tra(TreeNode *t,int val)
    {
        if(t==nullptr)
            return;
        tra(t->left,t->val);
        if(val-t->val<minVal)
            minVal=val-t->val;
        tra(t->right,t->val);
    }

501.二叉搜索树中的众数

501. 二叉搜索树中的众数 - 力扣(LeetCode)

解法:直接遍历
思路1:

直接想法:遍历得到一个有序数组然后通过map进行统计出现频率,key记录出现的值,value记录出现频率,再把map转化为vector进行排序,所以也需要自定义一个关于pair<int,int>的排序算法。这种适合所有的二叉树找众数。

class Solution {
public:
    map<int,int> p;
    //随便一种遍历方式就行
    void tra(TreeNode *t)
    {
        if(t==nullptr)  
            return ;
        p[t->val]++;
        tra(t->left);
        tra(t->right);
    }
    //map转vector排序函数
    bool static cmp(pair<int,int> a,pair<int,int> b)
    {
        return a.second>b.second;
    }
    vector<int> findMode(TreeNode* root) {
        tra(root);
        //map转vector
        vector<pair<int,int>> v(p.begin(),p.end());
        //排序
        sort(v.begin(),v.end(),cmp);
        vector<int> res;
        res.push_back(v[0].first);
        //记录相同频率众数
        for(int i=1;i<v.size();i++)
        {
            if(v[i].second==v[0].second)
                res.push_back(v[i].first);
            else
                return res;
        }
        return res;
    }
};
思路2:

中序遍历,这个比较难想到但是比较好理解。

首先我们只知道二叉搜索树中序遍历可以得到有序序列,两个一样的数必然是相邻的,这样统计频率就很好统计,我们只需要设置一个计数器表示这个数字的频率,前后一样的话就把计数器++。

问题是,我们要怎么设置这个计数器,在遍历的同时可以记录频率,又如何来判断前后两个数是否相同

首先,判断两个数是否相同,我们可以用上一道题的双指针,建立一个快慢指针,两个指针一前一后,判断两个数是否相同,相同的话就把计数器++。

现在来回答如何建立计数器的问题,我们需要两个全局变量

int maxcount=-1;//记录当前遍历过的最大频率的数的频率
int count=1;//记录当前正在遍历的数的频率

TreeNode *pre=nullptr;//慢指针
void tra(TreeNode *t)//传递的t是快指针

我们先来解决当前结点的数的频率记录问题,再去想全部的结点的频率记录问题

如果只对于一组快慢指针即只有两个结点,如果二者都不为空且数值一样,那么计数器是不是要++

如果慢指针为空,那说明慢指针还没有更新,还没有出现序列,频率自然就为1,和初始化一样

如果两者不为空数值不同,那说明当前结点的计数器还是1,不需要任何操作

我们把这段话实现一下

if(pre==nullptr)//还没有出现序列
	count=1;
else if(pre->val==t->val)//两个结点数值相同
	count++;
else    
	count=1;

现在来想如何把这两个结点的频率记录扩展到全部结点

没错,需要maxcount,maxcount记录当前结点的最大值,只有当前结点的count大于等于maxcount时我们才会把它放入我们的结果集res中

if(count==maxcount)
	res.push_back(t->val);
if(count>maxcount)
{
	maxcount=count;//更新maxcount
	res.push_back(t->val);
}

如果只是这样的话那这个不就太容易放入我们的结果集了吗?

所以我们每次更新maxcount要加入一个操作

res.clear();

即清空前面所有的结果集,注意这个是很重要的。而且在等于的时候我们并不会清除,只是会把答案放入其中。

1.函数参数和返回值

int maxcount=-1;//最大频率值
int count=1;//当前频率值
TreeNode *pre=nullptr;//慢指针
vector<int> res;//结果集
void tra(TreeNode *t)//快指针

2.终止条件

if(t==nullptr)
	return ;

3.本层代码逻辑

		//左
		tra(t->left);
		//中
        if(pre==nullptr)
            count=1;
        else if(pre->val==t->val)
            count++;
        else    
            count=1;
        pre=t;//慢指针更新,不要忘记
        if(count==maxcount)
            res.push_back(t->val);
        if(count>maxcount)
        {
            maxcount=count;
            res.clear();//清空结果集
            res.push_back(t->val);
        }
		//右
        tra(t->right);

完整代码:

class Solution {
public:
    int maxcount=-1;
    int count=1;
    TreeNode *pre=nullptr;
    vector<int> res;
    void tra(TreeNode *t)
    {
        if(t==nullptr)
            return ;
        tra(t->left);
        if(pre==nullptr)
            count=1;
        else if(pre->val==t->val)
            count++;
        else    
            count=1;
        pre=t;
        if(count==maxcount)
            res.push_back(t->val);
        if(count>maxcount)
        {
            maxcount=count;
            res.clear();
            res.push_back(t->val);
        }
        tra(t->right);
    }
    vector<int> findMode(TreeNode* root) {
        tra(root);
        return res;
    }
};

至此,只需要一遍遍历就把答案纪律完毕。

注:501需要及时复习

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

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

相关文章

Mysql—主从复制的slave添加及延迟回放

MySQL 主从复制是什么&#xff1f; ​ MySQL 主从复制是指数据可以从一个 MySQL 数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式&#xff0c;这样从节点不用一直访问主服务器来更新自己的数据&#xff0c;数据的更新可以在远程连接上进行&#xff0c;…

国产分布式数据库-tidb单机部署文档

tidb单机部署文档 1、创建用户 #创建用户 useradd tidb #设置密码 passwd tidb2、配置免密码登录 编辑/etc/sudoers文件,文末加入&#xff1a; tidb ALL(ALL) NOPASSWD:ALL如果想要控制某个用户(或某个组用户)只能执行root权限中的一部分命令, 或者允许某些用户使用sudo时…

充电桩设备升级扩展多段计费

一 项目背景 某省某市的一个充电桩项目近日收到业主需求&#xff0c;需在国庆节增加一个时间段&#xff08;深谷计费段&#xff09;&#xff0c;但充电桩设备仅支持4段&#xff08;尖时段&#xff0c;峰时段&#xff0c;平时段&#xff0c;谷时段&#xff09;&#xff0c;今…

【CoppeliaSim V4.7】The Python interpreter could not handle the wrapper script

[sandboxScript:error] The Python interpreter could not handle the wrapper script (or communication between the launched subprocess and CoppeliaSim could not be established via sockets). Make sure that the Python modules ‘cbor2’ and ‘zmq’ are properly i…

Spring MVC 基本配置步骤 总结

1.简介 本文记录Spring MVC基本项目拉起配置步骤。 2.步骤 在pom.xml中导入依赖&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.6</version><scope>…

关于javascript中防抖和节流的使用详解

防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常见的优化技巧&#xff0c;通常用于控制函数在短时间内频繁触发的场景&#xff0c;尤其是在处理用户输入、滚动、窗口大小调整等事件时。它们的主要目的是减少不必要的函数调用&#xff0c;…

想把泰文从文本上识别,什么软件工具好用呢?

泰文识别技术涉及将泰文图像转换成数字文本&#xff0c;主要通过光学字符识别&#xff08;OCR&#xff09;技术实现。这项技术广泛应用于文档处理、语言学习和翻译服务。实现泰文识别的方法包括使用手机应用程序、在线服务、专业软件&#xff0c;以及结合人工智能和机器学习。此…

UE5 C++: 插件编写04 | 自动增加前缀

准备工作 UObject* Asset UObject* Asset 通常指的是一个指向UObject的指针。UObject是Unreal Engine中的基类&#xff0c;几乎所有的引擎对象都继承自UObject。这个指针可以引用任何派生自UObject的对象&#xff0c;比如蓝图、材质、贴图、音频资源等资产。 如果你看到UObj…

【C++】——set和map的使用

文章目录 set的特性set初始化set迭代器和常见成员函数multisetmap的特性map初始化map迭代器和常见成员函数insert[]运算符重载multimap set的特性 自动排序&#xff1a; set中的元素会默认排升序存储唯一性&#xff1a; set中每个元素都是唯一的&#xff0c;如果插入一个已有元…

如何找到实力突出的建站公司,2024网络建站公司推荐

选择网站建设公司需要考虑公司以下几点&#xff1a; 是否对的业务需求的了解程度如何&#xff1f; 与公司的文化契合度 相同企业文化的公司&#xff0c;往往能取得很好的合作 沟通的方式 考虑&#xff1a;谁将是解决疑虑、查询、反馈的联系人&#xff0c;查询的响应时间是…

ShiroFilterFactoryBean登录认证成功后没有正常跳转到successUrl问题解决

问题出现&#xff1a; 分析&#xff1a;在配置了ShiroFilter之后&#xff0c;直接尝试在页面端访问login.jsp,但是login.jsp需要做认证过滤也就是FormAuthenticationFilter。 应为没有登录信息所以可想而知&#xff0c;会走ShiroFilterFactoryBean定义的loginUrl也就是认定为没…

VBA技术资料MF202:添加右键多按钮弹出菜单

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

使用PLSQL Developer快速连接数据库

文章目录 前言一、定义设置方式二、固定用户设置方式三、连接设置方式总结前言 PLSQL Developer是一个集成开发环境,由Allround Automations公司开发,专门面向Oracle数据库存储的程序单元的开发。该工具提供了多种设置方式,便于使用者在不需要输入用户名称、密码的情况下,…

易航网址导航系统V2.45完美去授权版

简介 易航网址导航系统V2.45完美去授权版 界面

2024 年 CSS 终于增加了垂直居中特性,效率翻倍!

在 2024 年的Chrome 123 版本中&#xff0c; CSS 原生可以使用 1 个 CSS 属性 align-content: center进行垂直居中。 有何魅力&#xff1f; 这个特性的魅力在哪儿呢&#xff1f;我举例给你看一下 <div style"align-content:center; height:200px; background: #614e…

18722 稀疏矩阵的运算

思路&#xff1a; 快速转置算法的基本思想是预先计算出转置后的三元组在新数组中的位置&#xff0c;然后直接将元素放到对应的位置上。这样做的好处是只需要遍历一次原数组&#xff0c;就可以完成转置操作。 步骤如下&#xff1a; 1. 初始化一个新的三元组数组&#xff0c;用于…

数据库性能监控如何做?简单3步实现慢SQL、长事务监控!

1.背景说明 对于使用关系型数据库的系统而言&#xff0c;在系统投产上线后&#xff0c;及时发现程序运行中的慢SQL语句&#xff0c;能有效降低系统运行风险&#xff1b;对于分布式应用系统来说&#xff0c;在系统日常运行中&#xff0c;为避免因数据库长事务导致主备切换风险&…

2024年 AI大模型我该买一张什么卡?

有钱啥也不用说&#xff0c;买张最贵的就是了。对囊中羞涩的我还说&#xff0c;我该买张什么样的显卡呢&#xff1f; 我的旧显卡RTX1060 6G&#xff0c;满负荷消耗功率110多瓦&#xff0c;几乎达到设计最大TDP&#xff0c;周日时拿了朋友的RTX3060Ti 8G&#xff0c;发现是锁算…

免费与付费代理IP工具的优缺点分析

面对市场上众多的代理IP工具&#xff0c;选择合适的工具成为一项挑战。本文将深入分析免费与付费代理IP工具的优缺点&#xff0c;协助您做出明智的选择。 一、免费代理IP工具的优缺点 优点&#xff1a; 零成本&#xff1a;最大的优点在于无需任何费用。对于预算有限的用户&a…

【资源一号02C卫星】

资源一号02C卫星 资源一号02C卫星是中国航天科技集团公司所属中国空间技术研究院负责研制生产的一颗重要遥感卫星。以下是关于该卫星的详细介绍&#xff1a; 一、基本信息 发射时间&#xff1a;2011年12月22日11时26分发射地点&#xff1a;中国太原卫星发射中心运载火箭&am…