算法力扣刷题记录 五十六【501.二叉搜索树中的众数】

前言

二叉搜索树操作,继续。
记录 五十六【501.二叉搜索树中的众数】


一、题目阅读

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

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

假定 BST 满足如下定义:

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

示例 1:
在这里插入图片描述

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

示例 2:

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

提示:

树中节点的数目在范围 [1, 10^4] 内
-10^5 <= Node.val <= 10^5

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)


二、尝试实现

依然使用二叉搜索树中序遍历得到有序递增序列的特性。

思路【直白想法】

  1. 借助数组,通过中序遍历将二叉搜索树中的值取出来。再在数组中操作。
  2. 在数组中使用双指针循环,判断一个值出现的次数,再和最大次数记录比较:
  • 如果比最大出现次数的记录小,那么不操作;
  • 如果相等,那么加入到返回值数组中;
  • 如果比最大出现次数的记录大,判断返回值数组中是否为空,先清空后加入。

代码实现【借助数组,额外开辟空间】

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void traversal(TreeNode* cur,vector<int>& nums){if(!cur) return;traversal(cur->left,nums);nums.push_back(cur->val);traversal(cur->right,nums);return;}vector<int> findMode(TreeNode* root) {vector<int> result;vector<int> nums;traversal(root,nums);int max = 0;for(int i = 0;i < nums.size();){int j=i+1;int count = 1;for(;j < nums.size();j++){if(nums[j] == nums[i]){count++;}else{break;}}if(count > max){if(!result.empty()) result.clear();result.push_back(nums[i]);max = count;}else if(count == max){result.push_back(nums[i]);}i = j;}return result;}
};

三、参考学习

参考学习链接

学习目标:如何在树中边遍历边确定众数?肯定还是双指针。尝试一下:有bug

class Solution {
public:int maxcount = 0;//记录最大次数int count = 1;//计数。TreeNode* pre =  nullptr;void traversal(TreeNode* cur,vector<int>& nums){if(!cur) return;traversal(cur->left,nums);if(pre && pre->val == cur->val){count++;}else if(pre && pre->val != cur->val){if(count > maxcount){if(!nums.empty()) nums.clear();nums.push_back(pre->val);maxcount = count;//最大值更新}else if(count == maxcount){nums.push_back(pre->val);}count = 1;//重新计数新的值pre = cur;//此处才更新pre}else if(!pre){pre = cur;//初始时,避免pre空}traversal(cur->right,nums);return;}vector<int> findMode(TreeNode* root) {vector<int> result;traversal(root,result);//处理最后}
};

使用时候,如何结束时也能操作元素呢?在cur->right后还有处理逻辑。

学习内容

  1. 双指针法解决:先说误区
  • 从借助数组的代码实现中发现遍历数组时,使用了i,j相当于i不动,j移动,统计这个元素出现次数。如果nums[j] != nums[i]说明nums[i]出现次数统计完毕。接下来比较count和max。
  • 没有想到可以相邻元素比较,如果相等,count++。count加一次,和max比较一次;不相等时,前面的count已经放到结果里。每一次都要进行count和max比较。
  • 尝试双指针错误在于,认为pre->val和cur->val不相等时,才更新pre,才比较count和max。正确:pre紧跟cur,把count和max的比较放到if外面,这样count更新,max更新。
  • 总结:错误——元素比较不相等时,统计完一个元素次数后放入结果;正确——每次元素比较,即使相等,也要判断count和max。
  1. 双指针代码修正
class Solution {
public:int maxcount = 0;//记录最大次数int count = 1;//计数。TreeNode* pre =  nullptr;void traversal(TreeNode* cur,vector<int>& nums){if(!cur) return;traversal(cur->left,nums);if(pre && pre->val == cur->val){count++;}else if(pre && pre->val != cur->val ){count = 1;//重新计数新的值}pre = cur;//初始时,避免pre空if(count > maxcount){if(!nums.empty()) nums.clear();nums.push_back(pre->val);maxcount = count;//最大值更新}else if(count == maxcount){nums.push_back(pre->val);}traversal(cur->right,nums);return;}vector<int> findMode(TreeNode* root) {vector<int> result;traversal(root,result);return result;}
};
  1. 迭代法:中序迭代模版,加中间节点处理逻辑。
  2. 普通二叉树如何求众数?
  • 普通二叉树数值没有任何关系,那么双指针法不成立。不过借助数组方法依然可以用。
  • 借助数组:遍历取出所有值放到vector里面,之后sort从小到大排个序,遍历数组;
  • 参考借助数组思路:用unordered_map统计元素出现次数,再把map转换成vector,再自定义比较函数,带入sort中,得到从大到小的排序vector。
  1. 普通二叉树求众数代码实现:
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void traversal(TreeNode* cur,unordered_map<int,int>& nums){if(!cur) return;nums[cur->val]++;traversal(cur->left);traversal(cur->right);}bool cmp(const pair<int,int>& a,const pair<int,int>& b) const{return a.second > b.second;}vector<int> findMode(TreeNode* root) {vector<int> result;unordered_map<int,int> map;traversal(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 = 0;i <vec.size();i++){if(vec[i].second == vec[0].second) result.push_back(vec[i].first);}return result;}
};

总结

【501.二叉搜索树中的众数】和【求普通二叉树的众数】
在这里插入图片描述
(欢迎指正,转载标明出处)

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

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

相关文章

【Socket编程】基于TCP协议实现客户端与服务端的通信

前言 由于TCP是面向连接的&#xff0c;所以在创建套接字之后还需要进入监听状态&#xff0c;监听状态下可以获取客户端的请求。获得请求之后&#xff0c;服务器需要接受连接&#xff0c;之后再处理事务。 实现服务端具体步骤 总的来说&#xff0c;TCP服务端主要实现以下步骤…

达梦数据库的系统视图v$dmwatcher

达梦数据库的系统视图v$dmwatcher 查询当前登录实例所对应的守护进程信息&#xff0c;注意一个守护进程可以同时守护多个组的实例&#xff0c;因此查询结果中部分字段&#xff08;N_GROUP、SWITCH_COUNT&#xff09;为守护进程的全局信息&#xff0c;并不是当前登录实例自身的…

0401-403组合逻辑电路的分析设计竞争冒险

组合逻辑电路的分析设计&竞争冒险 4.组合逻辑电路1.目录2.教学基本要求3.序 关于组合逻辑电路 4.1组合逻辑电路分析与设计一、组合逻辑电路分析二、组合逻辑电路的分析步骤&#xff1a;三、组合逻辑电路的分析举例例1 奇校验电路例2.对输入的二进制求反码例3.一个工厂发电的…

CSS 的环境变量函数env()

在CSS中&#xff0c;env() 函数并不是传统意义上的“环境变量”函数&#xff0c;如你在编程语言中可能遇到的那样。相反&#xff0c;env() 是CSS中的一个函数&#xff0c;它用于访问由宿主环境&#xff08;如浏览器&#xff09;提供给CSS的自定义属性&#xff08;也称为环境变量…

使用 PVE 自签 CA 证书签发新证书

前言 PVE 安装时会自动创建一个有效期 10 年的 CA 证书, 我们可以利用这个 CA 证书给虚拟机中的 Web 应用签发新的 TLS 证书用于提供 HTTPS 服务. 下面以 PVE 虚拟机中通过 Docker 跑的一个 雷池 应用为例进行演示. PVE 证书位置 官方文档: https://pve.proxmox.com/wiki/Pr…

服务攻防-框架安全(漏洞复现)

关闭靶场 sudo docker-compose down 运行此靶场 sudo docker-compose up -d 查看启动环境 sudo docker ps 运行dockers容器 docker exec -it 64052abd288b /bin/bash thinkphp框架 thinkphp 2 - rce漏洞复现 docker exec -it 731dbae0e0b5 /bin/bash 集成化工具扫描 可以命令…

Qt区分鼠标按下时移动的是哪个多边形

使用不同的鼠标事件处理器&#xff1a;为每个多边形分配不同的事件处理器&#xff0c;或者在同一个处理器中使用逻辑来区分。 检查鼠标点击位置&#xff1a;在鼠标按下事件中&#xff0c;检查鼠标的位置是否在某个多边形的边上或顶点上。 使用图形的标识符&#xff1a;给每个…

十五届蓝桥杯JAVA B组题目详解(持续更新中)

试题 B: 类斐波那契循环数 我发现蓝桥杯的题目现在就是要费时间去理解&#xff0c;所以还是审题很重要&#xff0c;这道题的思路就是&#xff0c;一个n位数的前n个数&#xff0c;都是对应的位数上的值&#xff0c;比如说12345&#xff0c;五位数是吧&#xff0c;那数列S的前五位…

phpstudy下载使用以及搭建本地SQL labs靶场

一&#xff0c;PHP study 小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; (xp.cn) 1&#xff0c;下载。 根据自己电脑系统下载对应的版本。 双击exe文件运行 选择下载目录&#xff08;路径不能有中文名&#xff09;。 2&#xff0c;使用。 启动阿帕奇和MySQ…

AI学习指南机器学习篇-自组织映射(Self-Organizing Maps,SOM)简介

AI学习指南机器学习篇-自组织映射&#xff08;Self-Organizing Maps&#xff0c;SOM&#xff09;简介 自组织映射&#xff08;Self-Organizing Maps&#xff0c;SOM&#xff09;是一种无监督学习算法&#xff0c;经常被用于降维、聚类和可视化高维数据。本篇博客将对SOM算法的…

数据库第二次作业

1.建立数据库 2.插入数据 3.完成查询 &#xff08;1&#xff09;、显示所有职工的基本信息。 &#xff08;2&#xff09;、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 &#xff08;3&#xff09;、求出所有职工的人数。 &#xff08;4&#xff09;、列…

FreeRTOS 信号量

信号量是操作系统中重要的一部分&#xff0c;信号量是任务间同步的一种机制&#xff0c;信号量可以用在多 任务访问同一资源时的资源管理。FreeRTOS 提供了多种信号量&#xff0c;按信号量的功能可分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。 使用信号量相关…

C#各种锁知识点

先上总结&#xff1a; 锁类型特点适用场景优点缺点自旋锁忙等待实现锁定&#xff0c;适合高并发短时间锁定高并发环境&#xff0c;短时间锁定&#xff0c;仅限单进程多线程同步开销低&#xff0c;避免线程上下文切换忙等待消耗CPU资源&#xff0c;不适合长时间锁定&#xff0…

组队学习——贝叶斯分类器

前言 本次数据继续沿用上一次主题的【组队学习——支持向量机-CSDN博客】 数据处理部分延续【组队学习——支持向量机】主题的处理办法对应划分训练集和验证集 模型选择 本次贝叶斯分类器模型的较多&#xff0c;常用的为高斯朴素贝叶斯分类器、多项式朴素贝叶斯分类器、伯努…

配置文件格式 XML 快速上手

文章目录 1.语法2.实例3.解析参考文献 XML&#xff08;Extensible Markup Language&#xff09;是可扩展标记语言&#xff0c;用来传输和存储数据。因为其允许用户自定义标记名称&#xff0c;具有自我描述性&#xff0c;可灵活地用于存储服务配置信息。 1.语法 XML 文档结构是…

JavaWeb总结

终于结束了JavaWeb的学习&#xff0c;个人感觉其实就是学习客户端与服务端交互的中间件&#xff0c;以及服务端处理的逻辑&#xff0c;来帮助我们构建整个项目的运转逻辑&#xff0c;从客户端到服务器再到客户端&#xff0c;核心是围绕着一系列的请求和响应如何处理&#xff0c…

嵌入式Linux学习: platform 设备驱动实验

在Linux中&#xff0c;Platform&#xff08;平台&#xff09;机制是一个重要的设备驱动管理框架&#xff0c;它主要在Linux 2.6内核及以后的版本中引入。Platform机制的主要目的是提供一种统一的方式来管理那些不直接挂靠在传统物理总线&#xff08;如USB、PCI、I2C、SPI等&…

信息学奥赛一本通 1270:【例9.14】混合背包

【题目描述】 一个旅行者有一个最多能装V公斤的背包&#xff0c;现在有n件物品&#xff0c;它们的重量分别是W1&#xff0c;W2&#xff0c;…,Wn &#xff0c;它们的价值分别为C1,C2,…,Cn。有的物品只可以取一次&#xff08;01背包&#xff09;&#xff0c;有的物品可以取无限…

如何理解ref toRef和toRefs

是什么 ref 生成值类型的响应式数据可用于模板和reactive通过.value修改值 ref也可以像vue2中的ref那样使用 toRef 针对一个响应式对象&#xff08;reactive&#xff09;的prop创建一个ref两者保持引用关系 toRefs 将响应式对象&#xff08;reactive封装&#xff09;转换…

论文阅读:Speculative RAG: Enhancing Retrieval Augmented Generation through Drafting

论文地址&#xff1a;https://arxiv.org/abs/2407.08223 RAG 将 LLM 的生成能力与外部知识源相结合&#xff0c;以提供更准确和最新的响应。最近的 RAG 进展侧重于通过迭代 LLM 完善或通过 LLM 的额外指令调整获得自我批判能力来改进检索结果。在这项工作中&#xff0c;作者介…