力扣第501题 二叉树的众数 c++ (暴力 加 双指针优化)

题目

501. 二叉搜索树中的众数

简单

相关标签

树   深度优先搜索   二叉搜索树   二叉树

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

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

假定 BST 满足如下定义:

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

示例 1:

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

示例 2:

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

提示:

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

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

思路和解题方法一(暴力)

  1. 定义一个私有函数searchBST,用于前序遍历二叉搜索树,并统计每个元素的频率。函数参数包括当前节点指针cur和存储元素频率的unordered_mapmap
  2. searchBST函数中,如果当前节点为空,则直接返回;否则,对当前节点的值进行统计,将当前节点的值作为map的键,并将对应的值加1,表示该元素出现的频率。
  3. 递归调用searchBST函数,传入当前节点的左子节点和map,再传入当前节点的右子节点和map,实现前序遍历。
  4. 定义一个静态成员函数cmp,用于比较两个pair类型的元素,按照频率降序排列。在排序时使用此比较函数。
  5. findMode函数中,首先创建一个空的unordered_map类型的map,用于存储元素及其频率。
  6. 如果输入的根节点为空,直接返回空的结果数组。
  7. 调用searchBST函数,传入根节点和map,统计二叉搜索树中每个元素的频率。
  8. map转化为vector类型,并使用sort函数对vector进行排序,排序方式为按照元素的频率降序排列。
  9. 创建一个空的结果数组result,将排序后的第一个元素的键(也就是出现频率最高的元素)添加到result中。
  10. 遍历排序后的vector,从第二个元素开始,如果其频率和第一个元素的频率相同,则将其键添加到result中;否则结束遍历。
  11. 返回结果数组result

复杂度

        时间复杂度:

                O(n logn)

  • 时间复杂度:

    • 前序遍历二叉树的时间复杂度为 O(n),其中 n 是二叉树的节点数。
    • 构建哈希表的过程中,对每个节点进行插入操作的平均时间复杂度为 O(1)。因此构建哈希表的时间复杂度也是 O(n)。
    • 对哈希表进行排序的时间复杂度为 O(nlogn)。
    • 综上所述,算法的时间复杂度为 O(n) + O(n) + O(nlogn) = O(nlogn)。

        空间复杂度

                O(n)

  • 空间复杂度:

    • 使用了一个哈希表来存储元素及其频率,哈希表的空间复杂度是 O(n)。
    • 将哈希表转换成了向量,空间复杂度仍然是 O(n)。
    • 保存结果的向量,最多可能存储所有节点的值,因此空间复杂度也是 O(n)。
    • 综上所述,算法的空间复杂度为 O(n)。

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 ;}// 静态成员函数,用于比较两个pair类型元素,按照频率降序排列static bool 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; // 存储元素及其频率的map,key为元素,value为频率vector<int> result; // 结果数组if (root == NULL) return result; // 根节点为空,直接返回空结果数组searchBST(root, map); // 统计二叉搜索树中每个元素的频率vector<pair<int, int>> vec(map.begin(), map.end()); // 将map转换为vectorsort(vec.begin(), vec.end(), cmp); // 按照频率降序排列result.push_back(vec[0].first); // 将频率最高的元素添加到结果数组中for (int i = 1; i < vec.size(); i++) {// 遍历排序后的vector,如果元素频率与第一个元素的频率相同,则添加到结果数组中;否则结束遍历if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result; // 返回结果数组}
};

 思路和解题方法二(双指针 加 时时优化)

  1. 使用了一个全局变量 maxCount 来记录最大频率,使用 count 来统计当前节点值出现的频率。同时,引入了一个 pre 变量来记录前一个访问的节点,以便比较当前节点与前一个节点的值是否相同。
  2. 函数 searchBST 是进行中序遍历的辅助函数,通过递归遍历左子树、处理当前节点、递归遍历右子树的顺序进行搜索。在处理当前节点时,首先判断当前节点值与前一个节点值是否相同,若相同则将 count 增加 1,否则将 count 重置为 1。然后,根据 count 的大小与 maxCount 进行比较,并更新 maxCountresult。如果 countmaxCount 相同,说明当前节点值出现的频率与最大频率相同,将其加入 result 中。如果 count 大于 maxCount,则更新 maxCount 并清空 result,将当前节点值放入 result 中。
  3. findMode 函数中,初始化各个变量,然后调用 searchBST 开始搜索,并返回结果数组 result

复杂度

        时间复杂度:

                O(n)

时间复杂度是O(n),其中n是二叉搜索树中的节点数。因为我们需要遍历所有的节点来统计它们的频率。

        空间复杂度

                O(1)

不利用额外空间

c++ 代码

class Solution {
private:int maxCount = 0; // 最大频率int count = 0; // 统计频率TreeNode* pre = NULL; // 前一个节点vector<int> result; // 存储结果的向量// 中序遍历二叉搜索树,搜索出现频率最高的节点值void searchBST(TreeNode* cur) {if (cur == NULL) return; // 递归终止条件,当前节点为空searchBST(cur->left); // 左子树// 统计频率if (pre == NULL) { // 第一个节点count = 1;} else if (pre->val == cur->val) { // 与前一个节点数值相同count++;} else { // 与前一个节点数值不同count = 1;}pre = cur; // 更新上一个节点if (count == maxCount) { // 如果和最大频率相同,将节点值放进result中result.push_back(cur->val);}if (count > maxCount) { // 如果频率大于最大频率maxCount = count;   // 更新最大频率result.clear();     // 清空result,之前result中的元素都无效了result.push_back(cur->val);}searchBST(cur->right); // 右子树return ;}public:vector<int> findMode(TreeNode* root) {count = 0;maxCount = 0;pre = NULL; // 初始化前一个节点为空result.clear(); // 清空result向量searchBST(root); // 调用中序遍历函数搜索出现频率最高的节点值return result; // 返回结果向量}
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

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

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

相关文章

竞赛 深度学习 opencv python 实现中国交通标志识别

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…

前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— JS进阶(三)

思维导图 1.编程思想 1.1 面向过程编程 1.2 面向对象编程 (oop) 2. 构造函数 3. 原型 3.1 原型 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IE…

C#和JS交互之Microsoft.ClearScript.V8(V8引擎)

之前测试了很多JS引擎&#xff0c;都只支持es5语法&#xff0c;不支持执行es6&#xff0c;测试了下微软的V8反正能跑通&#xff0c;应该是支持的。还得是微软呀。 如图&#xff1a;安装相关包&#xff1a; 这是参考的官方V8代码 using Microsoft.ClearScript.JavaScript; us…

VRRP 虚拟路由器冗余协议的解析和配置

VRRP的解析 个人简介 原理和HSRP的差不多&#xff0c;少了一些状态就只有了三种状态 还有不同的就是VRRP严格按照抢占要求 一个VRRP组中具有最高优先级的设备成为Master路由器缺省优先级为100若优先级相同&#xff0c;具有最高接口IP地址最大的路由器成为Master路由器抢占(Pr…

uniapp微信小程序自定义封装分段器。

uniapp微信小程序自定义封装分段器。 话不多说先上效果 这里我用的是cil框架 vue3 下面贴代码 组价代码&#xff1a; <template><view class"page"><viewv-for"(item, index) in navList":key"index"click"changeNav(ind…

KEIL5添加沁恒的ch55x芯片(其他非arm和stm32芯片也可使用类似的方法)

准备工作 参考&#xff1a;https://www.iotword.com/8615.html 已经安装好keil5的软件环境 烧录工具下载 沁恒烧录工具地址&#xff0c;下载安装后如下图 操作步骤 打开从沁恒官网下载安装好的WHCISPTOOL软件 安装下图中的操作方式完成对安装软件keil5中的配置文件的生…

网工实验笔记:匹配工具ACL的使用

一、概述 访问控制列表简称为ACL&#xff0c;它使用包过滤技术&#xff0c;在路由器上读取第3层及第4层包头中的信息&#xff0c;如源地址、目的地址、源端口和目的端口等&#xff0c;根据预告定义好的规则对包进行过滤从而达到访问控制的目的。ACL分很多种&#xff0c;不同场…

【Redis】Set集合相关的命令

目录 命令SADDSMEMBERSSISMEMBERSCARDSPOPSMOVESREMSINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令 SADD 将⼀个或者多个元素添加到set中。注意&#xff0c;重复的元素⽆法添加到set中。 SADD key member [member ...]SMEMBERS 获取⼀个set中的所有元素&#xff0…

排序算法——选择排序

一、介绍&#xff1a; 选择排序就是按照一定的顺序从选取第一个元素索引开始&#xff0c;将其储存在一个变量值中&#xff0c;根据排序规则比较后边每一个元素与这个元素的大小&#xff0c;根据排序规则需要&#xff0c;变量值的索引值进行替换&#xff0c;一轮遍历之后&#x…

知识增强语言模型提示 零样本知识图谱问答10.8+10.11

知识增强语言模型提示 零样本知识图谱问答 摘要介绍相关工作方法零样本QA的LM提示知识增强的LM提示与知识问题相关的知识检索 实验设置数据集大型语言模型基线模型和KAPIN评估指标实现细节 实验结果和分析结论 摘要 大型语言模型&#xff08;LLM&#xff09;能够执行 零样本cl…

基于FPGA的视频接口之千兆网口(四配置)

简介 相信网络上对于FPGA驱动网口的开发板、博客、论坛数不胜数,为何博主需要重新手敲一遍呢,而不是做一个文抄君呢!因为目前博主感觉网络上描述的多为应用层上的开发,非从底层开始说明,本博主的思虑还是按照老规矩,按照硬件、底层、应用等关系,使用三~四篇文章,来详细…

铁道交通运输运营3D模拟仿真实操提供一个沉浸、高效且环保的情境

VR模拟果蔬运输应急处理场景在农产品物流行业中具有重要的意义。这种模拟技术为农产品运输提供了全新的、更高效和更安全的方式来模拟真实世界的应急情况&#xff0c;帮助操作人员、研究者和管理者更好地理解和应对可能的运输风险措施。 VR模拟果蔬运输应急处理场景可以模拟出各…