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

news2024/10/7 12:22:36

题目

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转换为vector
        sort(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.coloradmin.cn/o/1083240.html

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

相关文章

C++入门篇---(1)命名空间与缺省参数

1.前言: c兼容C语言,C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等。 因此你可以理解为c是在c语言的基础上进行扩展的升级版. 它补充了C语言语法的不足&#xff0c;以及C是如何对C语言设计不合理…

【算法|双指针系列No.6】leetcode LCR 179. 查找总价格为目标值的两个商品

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

如何优化前端图像和多媒体资源?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【Redis】Set集合相关的命令

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

【RocketMQ】RocketMQ5.0新特性(一)- Proxy

为了向云原生演进&#xff0c;提高资源利用和弹性能力&#xff0c;RocketMQ在5.0进行了架构的调整与升级&#xff0c;先来看新特性之一&#xff0c;增加了Proxy层。 增加Proxy代理层 计算存储分离 计算存储分离是一种分层架构&#xff0c;将计算层与存储层分开。 计算层指的是…

There was an error committing your changes: File could not be edited

使用github完成commit changes时报的一个错误&#xff0c;最终原因是没有填写Extended description

初学vue,想自己找个中长期小型项目练练手,应该做什么?

前言 可以试着做一两个完整的后台管理项目后再去做其他的&#xff0c;下面推荐一些github上的vue后台管理的项目&#xff0c;可以自己选择性的练一下手 Vue2 1、iview-admin Star: 16.4k 基于 iview组件库开发的一款后台管理系统框架&#xff0c;提供了一系列的强大组件和基…

湖州OLED透明拼接屏技术应用引领现代化旅游观光方式

湖州市位于中国浙江省北部&#xff0c;拥有悠久的历史和丰富的文化遗产。湖州市以其美丽的湖泊和秀丽的自然风光而闻名。 作为中国重要的历史文化名城之一&#xff0c;湖州市有着丰富的文化遗产和历史资源&#xff0c;如古城墙、古建筑和古镇等。 这为OLED透明拼接屏技术的应用…

一文讲解图像梯度

简介&#xff1a; ​ 图像梯度计算的是图像变化的幅度。对于图像的边缘部分&#xff0c;其灰度值变化较大&#xff0c;梯度值变化也较大&#xff1b;相反&#xff0c;对于图像中比较平滑的部分&#xff0c;其灰度值变化较小&#xff0c;相应的梯度值变化也较小。一般情…

C++标准模板(STL)- 类型支持 (数值极限,round_style,is_iec559,is_bounded)

数值极限 定义于头文件 <limits> 定义于头文件 <limits> template< class T > class numeric_limits; numeric_limits 类模板提供查询各种算术类型属性的标准化方式&#xff08;例如 int 类型的最大可能值是 std::numeric_limits<int>::max() &…

聚观早报 | 首个“5G-A智慧家庭”发布;李鹏称5G-A是5G发展选择

【聚观365】10月12日消息 首个“5G-A智慧家庭”发布 李鹏称5G-A是5G发展的自然选择 新版努比亚Z50S Pro开售 英特尔锐炫A580显卡全球同步上市 vivo X100系列年底登场 首个“5G-A智慧家庭”发布 在全球移动宽带论坛&#xff08;MBBF2023&#xff09;期间&#xff0c;du联合…

中国长序列地表冻融数据集(1978-2015)

简介&#xff1a; 中国长序列地表冻融数据集——双指标算法(1978-2015)采用SMMR&#xff08;1978-1987&#xff09;、SSM/I&#xff08;1987-2009&#xff09;和SSMIS&#xff08;2009-2015&#xff09;逐日亮温数据&#xff0c;由双指标&#xff08;TB,37v&#xff0c;SG&…

【C++进阶之路】C++11(中)

一、可变参数模板 1.基本概念 想要了解C语言的可变参数列表的原理可见&#xff1a;可变参数列表 这个跟C语言的可变参数列表有一定的关系,常用的printf与scanf的参数就包含可变参数列表。 那么可变参数模板是什么呢&#xff1f;举个例子便一目了然。 template<class...Arg…

Qt Quick读取本地文件并显示成表格

&#x1f680;作者&#xff1a;CAccept &#x1f382;专栏&#xff1a;Qt Quick 文章目录 &#x1f34e;C代码部分实现&#x1f680;C类注册到QML中&#x1f382;QML部分实现&#x1f330;小知识点⭐C与QML进行交互⭐将运行路径进行传递保证程序的稳定性⭐QML中定义信号其默认…

【Proteus仿真】【STM32单片机】智能加湿器设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用LCD1602液晶、按键、蜂鸣器、DHT11温湿度传感器、水位传感器、PCF8591 ADC、继电器、加湿装置等。 主要功能&#xff1a; 系统运行后&#xff0…

从零开始:深入理解Kubernetes架构及安装过程

K8s环境搭建 文章目录 K8s环境搭建集群类型安装方式环境规划克隆三台虚拟机系统环境配置集群搭建初始化集群&#xff08;仅在master节点&#xff09;配置环境变量&#xff08;仅在master节点&#xff09;工作节点加入集群&#xff08;knode1节点及knode2节点&#xff09;安装ca…

吃鸡高手秘籍大揭秘,享受顶级游戏干货!

大家好&#xff01;作为吃鸡行家&#xff0c;今天我将揭示一些与众不同、足够吸引力的内容&#xff0c;帮助您提高游戏战斗力并分享顶级游戏作战干货。 首先&#xff0c;让我们推荐一些绝地求生作图工具。这些工具可以帮助您在游戏中更好地制作作战图和规划策略&#xff0c;让您…

基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持本地图片上传与回显的功能实现(二)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 排除路径&#xff0c;增加avatar图片 # security配置 security:# 排除路径excludes:# 静态资源- /*.html…

Python+Tkinter 图形化界面基础篇:集成数据库

PythonTkinter 图形化界面基础篇&#xff1a;集成数据库 引言为什么选择 SQLite 数据库&#xff1f;集成 SQLite 数据库的步骤示例&#xff1a;创建一个任务管理应用程序步骤1&#xff1a;导入必要的模块步骤2&#xff1a;创建主窗口和数据库连接步骤3&#xff1a;创建数据库表…

Spring源码解析—— AOP代理的生成

本文已经收录到大彬精心整理的大厂面试手册&#xff0c;包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等高频面试题&#xff0c;非常实用&#xff0c;有小伙伴靠着这份手册拿…