当前位置: 首页 > news >正文

Leetcode:501. 二叉搜索树中的众数(C++)

目录

问题描述:

实现代码与解析:

通用写法(递归):

原理思路:

依据二叉搜索树特性写法(递归):

原理思路:

迭代:

原理思路:


问题描述:

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

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

假定 BST 满足如下定义:

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

示例 1:

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

示例 2:

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

实现代码与解析:

通用写法(递归):

class Solution {
public:
    //遍历
    void traversal(TreeNode* cur,unordered_map<int,int>& map)
    {
        if(cur==NULL) return;
        map[cur->val]++;//对应值的频率加一
        traversal(cur->left,map);
        traversal(cur->right,map);
    }
    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;//<结点值,频率>
        vector<int> result;//结果
        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=1;i<vec.size();i++)
        {
            if(vec[i].second==vec[0].second)
            {
                result.push_back(vec[i].first);
            }
            else
            {
                break;
            }
        }
        return result;
    }
};

原理思路:

        二叉树求众数的通用写法,非二叉搜索树也可以用。

        1、首先用map<结点值,频率>来接收遍历结果,

        2、然后再依据频率排序,由于map只能依据key来排序,不能依据value,所以我们这里先转化成vector<pair<int,int>>来进行排序。

        3、最后取出频率最大的一个值或多个值,放入result数组中。

下面介绍二叉搜索树的写法,当然二叉搜索树也可以用上面这种通用写法。

依据二叉搜索树特性写法(递归):

class Solution {
public:
    TreeNode* pre=NULL;//记录前一个结点
    int maxCount=0;//最大频率
    int count=0;//统计频率
    vector<int> vec;//记录众数,可能有多个,我们用数组记录
    void traversal(TreeNode* cur)
    {
        if(cur==NULL) return;
        traversal(cur->left);//左
        //第一个结点
        if(pre==NULL)
        {
            count=1;//更新当前频率
        }
        //若与前一结点值相同
        else if(pre->val==cur->val)
        {
            count++;
        }
        //与前一个结点值不同
        else
        {
            count=1;
        }
        //若当前频率等于最大频率
        if(count==maxCount)
        {
            vec.push_back(cur->val);//记录该结点值
        }
        //若当前频率大于最大频率
        else if(count>maxCount)
        {
            maxCount=count;//更新最大值
            vec.clear();//最大频率已经改变,凭空之前的记录值
            vec.push_back(cur->val);
        }
        pre=cur;//跟新前一结点
        traversal(cur->right);//右
    }
    vector<int> findMode(TreeNode* root) 
    {
        traversal(root);
        return vec;
    }
};

原理思路:

        和二叉搜索树一样,我们肯定还是在中序处理结点。

        1、首先我们要定义maxCount来记录最大频率,count来记录当前遍历结点值的频率,在过程中要不断更新,还要定义一个pre来记录前一个结点值,以及result数组来记录结果。

        2、中序处理:首先要获取当前count值,若pre为空,说明是第一个结点,直接令count=1即可。

        3、若pre不空,判断pre的值与当前结点值是否相等,若相等,count++,若不相等,依旧令count=1,我们就得到了当前count值。

        4、然后我们就要用count和maxCount做比较,若相等,说明此元素为当前遍历过的结点中的最大频率相同的众数,result记录其值,若count大于maxCount,说明此元素的频率超过了最大频率,我们清空result,将新的最大频率的值放入result数组中,清空result是容易忽略的点,大家要注意一下,result一定要清空,因为此时最大频率已经变了,之前记录的结果显然需要去除掉。

        5、最后别忘了,更新pre,记录结点,作为下一个结点的前一个结点。

        其实注释写的已经很具体了,大家可以结合注释看。

迭代:

class Solution {
public:
    vector<int> findMode(TreeNode* root) 
    {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = NULL;
        int maxCount = 0; // 最大频率
        int count = 0; // 当前频率
        vector<int> result;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) 
            { 
                st.push(cur); 
                cur = cur->left;                
            } 
            else 
            {
                cur = st.top();
                st.pop(); 
                // 第一个节点                     
                if (pre == NULL) 
                { 
                    count = 1;
                }
                // 与前一个节点数值相同 
                else if (pre->val == cur->val) 
                { 
                    count++;
                } 
                // 与前一个节点数值不同
                else 
                { 
                    count = 1;
                }
                if (count == maxCount) 
                { 
                    result.push_back(cur->val);
                }
                if (count > maxCount) 
                { 
                    maxCount = count;   // 更新最大频率
                    result.clear();     // 清空result
                    result.push_back(cur->val);
                }
                pre = cur;
                cur = cur->right;               
            }
        }
        return result;
    }
};

原理思路:

        中序迭代遍历,没什么可说的,和递归原理相同。

相关文章:

  • mysql数据库管理-服务器语句超时处理参数
  • 【Linux】工具使用
  • 从零备战蓝桥杯——动态规划(子序列篇)
  • React 学习笔记总结(八)
  • 基于FPGA的UDP 通信(三)
  • 用HTML写一个2023跨年动画代码(烟花+自定义文字+背景音乐+雪花+倒计时)
  • 聊聊VMware的三种网络模式
  • 终极 3D 图形工具包:Ab3d.PowerToys 10.2.X Crack
  • C++ 类和对象(三)
  • R语言实现牛顿插值
  • jenkins结合gitlable企业集成部署实战
  • 前端面试题——React重点
  • 超级详细的PMP复习方法,3A拿下考试不发愁!
  • C语言进阶——通讯录
  • C#语言实例源码系列-实现停车场系统项目-下
  • 2017-09-12 前端日报
  • Babel配置的不完全指南
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • es6要点
  • export和import的用法总结
  • idea + plantuml 画流程图
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • JavaScript函数式编程(一)
  • javascript面向对象之创建对象
  • Joomla 2.x, 3.x useful code cheatsheet
  • SpiderData 2019年2月13日 DApp数据排行榜
  • windows-nginx-https-本地配置
  • 飞驰在Mesos的涡轮引擎上
  • 终端用户监控:真实用户监控还是模拟监控?
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​io --- 处理流的核心工具​
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (03)光刻——半导体电路的绘制
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (二)JAVA使用POI操作excel
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转载)OpenStack Hacker养成指南
  • .bat批处理出现中文乱码的情况
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .Net6 Api Swagger配置
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • @Autowired和@Resource装配
  • @ResponseBody
  • [145] 二叉树的后序遍历 js
  • [AIGC] Java 和 Kotlin 的区别
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BZOJ3211]:花神游历各国(小清新线段树)
  • [C++][数据结构][算法]单链式结构的深拷贝