二叉搜索树中的众数

news2025/2/27 17:26:12

1题目

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

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

假定 BST 满足如下定义:

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

示例 1:

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

示例 2:

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

2链接

题目链接:501. 二叉搜索树中的众数 - 力扣(LeetCode)

视频链接:不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数_哔哩哔哩_bilibili

3解题思路

如果不是二叉搜索树

如果不是二叉搜索树,最直观的方法一定是把这个树都遍历了,用map统计频率,把频率排个序,最后取前面高频的元素的集合。

具体步骤如下:

1、这个树都遍历了,用map统计频率

至于用前中后序哪种遍历也不重要,因为就是要全遍历一遍,怎么个遍历法都行,层序遍历都没毛病!

2、把统计的出来的出现频率(即map中的value)排个序

有的同学可能可以想直接对map中的value排序,还真做不到,C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。

所以要把map转化数组即vector,再进行排序,当然vector里面放的也是pair<int, int>类型的数据,第一个int为元素,第二个int为出现频率。

3、取前面高频的元素

此时数组vector中已经是存放着按照频率排好序的pair,那么把前面高频的元素取出来就可以了。

是二叉搜索树

既然是搜索树,它中序遍历就是有序的。、

在二叉树:搜索树的最小绝对差 (opens new window)中我们就使用了pre指针和cur指针的技巧,这次又用上了。

弄一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。

而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。

此时又有问题了,因为要求最大频率的元素集合(注意是集合,不是一个元素,可以有多个众数),如果是数组上大家一般怎么办?

应该是先遍历一遍数组,找出最大频率(maxCount),然后再重新遍历一遍数组把出现频率为maxCount的元素放进集合。(因为众数有多个)

这种方式遍历了两遍数组。

那么我们遍历两遍二叉搜索树,把众数集合算出来也是可以的。

但这里其实只需要遍历一次就可以找到所有的众数。

那么如何只遍历一遍呢?

如果 频率count 等于 maxCount(最大频率),当然要把这个元素加入到结果集中(以下代码为result数组)

result怎么能轻易就把元素放进去了呢,万一,这个maxCount此时还不是真正最大频率呢。

所以下面要做如下操作:

频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了。

4代码

/**
 * 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 searchBST(TreeNode* cur, unordered_map<int,int>& map) {
        if (cur == nullptr) 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;
    }
    vector<int> findMode(TreeNode* root) {
        unordered_map<int, int> map; //key:元素,value:出现的频率
        vector<int> result;
        if (root == nullptr) 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 & cur)法
class Solution {
public:
    int count = 0;
    int maxCount = 0;
    TreeNode* pre = nullptr;
    vector<int> result;
    void traversal (TreeNode* cur) {
        if (cur == nullptr) return ;
        //左
        traversal(cur->left); 
        //中
        if (pre == nullptr) count = 1;
        else if (cur->val == pre->val) count++; //cur节点与pre节点数值相同,计数+1
        else count = 1; //cur节点与pre节点数值不相同,重置cur->val的计数
        pre = cur; //双指针依次后移
        if (count == maxCount) result.push_back(cur->val);// 如果和最大值相同,放进result中
        if (count > maxCount) {
            maxCount = count; //更新最大频率
            result.clear(); //清空result数组中储存的所有最大元素,因为找到了更大的
            result.push_back(cur->val); //把这个更大的元素放入result数组
        }
        //右
        traversal(cur->right);
        return ;
    }
    vector<int> findMode(TreeNode* root) {
        traversal(root);
        return result;
    }
};

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

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

相关文章

存储资源调优技术——智能缓存分区

SmartPratition智能缓存分区 基本概念 本质上就是一种Cache分区技术 通过对系统核心资源的分区&#xff08;隔离不同业务所需要的缓存资源&#xff09;&#xff0c;保证关键应用的性能 工作原理 用户可以以LUN或文件系统为单位设置SmartPartition分区 每个SmartPartition分区的…

Qt文件系统源码分析—第二篇QSaveFile

范围 深度 首先指定深度分析深度&#xff0c;否者会陷入代码海洋之中。 本文只分析到Win32 API/Windows Com组件/STL库函数层次&#xff0c;再下层代码不做探究 本文主要了解QSaveFile及其具体实现&#xff0c;使用到父类数据的地方只讨论关键点 QT Private类 大部分Qt类有…

基础篇-设计模式

单例模式&#xff1a; 注意&#xff1a;这里的唯一实例不是使用时候才创建,而是构造时候就会创建; 注意&#xff1a;提前创建了对象&#xff0c;并不是调用时候才创建 解决方法&#xff1a; 枚举饿汉单例&#xff1a; 注意: 饿汉式枚举不会通过反序列化破坏单例 懒汉模式&…

SQL笔记(3)——MySQL数据类型

学习MySQL&#xff0c;通常应该是先学习数据类型的&#xff0c;因为不管是开发还是MySQL中&#xff0c;每个数据对象都有其对应的数据类型&#xff0c;MySQL提供了丰富的数据类型&#xff0c;如在创建表的时候就需要指定列的数据类型&#xff0c;在向表中插入数据时&#xff0c…

ElasticSearch(一)下载及安装(windows)

1. 官网 ElasticSearch官网地址ElasticSearch生态组件下载地址Kibana下载地址ik中文分词插件 备注&#xff1a;网址打不开&#xff0c;或者打开速度慢是正常情况。 2. 解压后目录结构 bin &#xff1a;脚本文件&#xff0c;包括启动elasticsearch&#xff0c;安装插件&#…

目录打开显示提示文件或目录损坏且无法读取、文件或目录损坏且无法读取的破解之道

咱们在平日工作时&#xff0c;通常都会将资料放进不同的目录中&#xff0c;方便咱们找到&#xff0c;随着时间的推移就会产生有越来越多目录。最近有位用户了这样一个问题&#xff0c;就是目录无论怎么都无法打开&#xff0c;这样就无法浏览、使用里面的资料了&#xff0c;影响…

springboot sharding-jdbc 主从 读写分离

目录 1 mysql 主从搭建 1.1 docker mysql 主从搭建 1.2 非docker mysql 主从搭建 2 springboot sharding-jdbc 主从 读写分离 2.1 pom 加依赖 2.1 yml 配置文件 3 测试 -> 直接使用 就是读写分离 3.1 实体类User -> 数据字段 对象字典 3.2 Mapper -> 增删改查…

Nomogram | 盘点一下绘制列线图的几个R包!~(二)

1写在前面 不知道各位小伙伴的五一假期过的在怎么样&#xff0c;可怜的我感冒了。&#x1f637; 今天继续之前没有写完的列线图教程吧&#xff0c;再介绍几个制作列线图的R包。&#x1f920; 2用到的包 rm(list ls())library(tidyverse)library(survival)library(rms)library(…

新闻文本关键词提取有哪些算法,这些算法的特点以及应用,以及不足方面的解决办法

目录 一、新闻文本关键词提取算法 1. TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;算法 2. TextRank算法 3. 词向量算法 4. 深度学习算法 5. 主题模型算法 二、这些算法的不足方面的解决办法 1. TF-IDF算法&#xff1a; 2. TextRank算法&…

一文彻底读懂nginx中的location指令

Nginx主配置文件结构 location 介绍 location是Nginx中的块级指令(block directive),&#xff0c;location指令的功能是用来匹配不同的url请求&#xff0c;进而对请求做不同的处理和响应&#xff0c;这其中较难理解的是多个location的匹配顺序&#xff0c;本文会作为重点来解释…

Effective Modern C++

模板类型推导 template<typename T> void f(T& parms);//reference template<typename T> void f(const T& parms);//const ref template<typename T> void f(T* parms);//pointer template<typename T> void f(T&& parms);//univers…

通讯录的实现(动态完结版)

&#x1f349;博客主页&#xff1a;阿博历练记 &#x1f4d6;文章专栏&#xff1a;c语言&#xff08;初阶与进阶&#xff09; &#x1f357;代码仓库&#xff1a;阿博编程日记 &#x1f339;欢迎关注&#xff1a;欢迎友友们点赞收藏关注哦 文章目录 &#x1f354;前言&#x1f…

java 倒计时实现的方式

倒计时的实现方法有很多种&#xff0c;本文给大家介绍其中一种&#xff0c;最简单的一种实现方式&#xff0c;也是最方便的一种方式&#xff0c;希望能帮到大家。 1、 java中倒计时是利用循环来实现的&#xff0c;我们可以使用循环语句来实现。 2、 java中使用 bool类的 setTim…

python相对路径与绝对路径

9.1 Python 绝对路径与相对路径 - 知乎 (zhihu.com) 目录 1. 绝对路径 1.1 概念 1.2 用绝对路径打开文件 1.2 相对路径 1.3 python路径表示的斜杠问题 1. 绝对路径 1.1 概念 绝对路径 指完整的描述文件位置的路径。绝对路径就是文件或文件夹在硬盘上的完整路径。 在 Win…

Spring--AOP详细介绍--和详细代码演示证明理解

目录 Spring--AOP详细介绍 基本介绍 代码演示—入门 需求说明 定义一个接口类Vehicle 定义一个实现接口类的Car类 定义一个实现接口类的Ship类 创建测试类Test.java 来思考一下&#xff0c; 解决方案-动态代理方式-2 修改 Car类 修改 Ship类 创建VehicleProxyProvid…

AI已经成立社区了,一个个比真人还真

文章目录 nainaimichirper川普的入驻英文版 nainaimi nainaimi是一个13岁的学生&#xff0c;一小时前&#xff0c;被一群人拖到体育馆&#xff0c; 那时的她还很胆小&#xff0c;只能哭诉着那些人的残忍和恶毒 结果半个小时前&#xff0c;她又被拖入了体育馆&#xff0c;这一…

跟着我学 AI丨让计算机看懂世界

计算机视觉是一种利用计算机和数学算法来处理、分析和识别数字影像的技术。这项技术在近年来得到了快速发展&#xff0c;应用范围也越来越广泛&#xff0c;它已经成为了人工智能领域中的重要分支之一。 技术原理 计算机视觉技术主要涉及图像处理、模式识别和机器学习等方面的技…

自然语言处理与其Mix-up数据增强方法报告

自然语言处理与其Mix-up数据增强方法 1绪论1.课题背景与意义1.2国内外研究现状 2 自然语言经典知识简介2.1 贝叶斯算法2.2 最大熵模型2.3神经网络模型 3 Data Augmentation for Neural Machine Translation with Mix-up3.1 数据增强3.2 对于神经机器翻译的软上下文的数据增强3.…

微信小程序学习实录2(下拉刷新、下拉加载更多、小程序事件、PHP后端代码、刷新无数据解决方案)

微信小程序学习实录2 一、全局配置1.启用lazyCodeLoading2.启用enablePullDownRefresh 二、设置全局变量三、页面初始化数据四、当前页面进入执行下拉刷新五、监听用户下拉动作六、页面上拉触底事件的处理函数七、PHP后端对接API八、常见问题1.不显示下拉加载...2.下拉不刷新数…

【Fluent】导出瞬态计算过程每一秒或每一个时间步的各个坐标/节点的物理量-温度场-压力场

一、功能需求 如果你进行的是稳态计算&#xff0c;你需要将物理场中的每一个节点上的物理量数据&#xff08;例如温度、压力&#xff09;导出成类似txt或Excel表格的文件。 文件里的内容形式是&#xff1a;每一行中有节点ID、节点的XYZ坐标、物理量&#xff08;温度压力等&am…