• 2021.1.31 刷题(前K个高频元素-桶排序)


    题目链接:https://leetcode-cn.com/problems/top-k-frequent-elements/
    题目描述:

    代码:
    方法一:哈希+桶排序
    首先依旧使用哈希表统计频率,统计完成后,创建一个数组(桶),每个桶存储出现频率相同的数。桶的下标表示数出现的频率,即第 i 个桶中存储的数出现的频率为 i。
    把数都放到桶之后,从后向前遍历桶,最先得到的 k 个数就是出现频率最多的的 k 个数。

    class Solution {
    public:
        vector<int> topKFrequent(vector<int>& nums, int k) {
            unordered_map<int, int> record;
            vector<int> result;
             
            //元素值作为key,相同元素频率作为value
            int max_freq = 0;
            for(int i = 0; i < nums.size(); i++)
            {
               record[nums[i]] += 1;  
               if(record[nums[i]] > max_freq)
                    max_freq = record[nums[i]] ;
            }
            
            vector<stack<int>> bucket(max_freq+1, stack<int>());
            //遍历record,将频率相同的元素放在一起
            for(auto &iter :record )
            {
                bucket[iter.second].push(iter.first);
                //cout << bucket[iter.second].top() << endl;
               
            }
            
    
            for(int i = bucket.size() - 1; i > 0 && result.size() < k; i-- )
            {
                while(!(bucket[i].empty()))
                {
                    result.push_back(bucket[i].top());
                    bucket[i].pop();
                }
                   
            }
            return result;
        }
    };
    

    方法二:小顶堆
    C++定义:priority_queue<Type, Container, Functional>
    Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
    当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
    一般是:

    //升序队列,小顶堆
    priority_queue <int,vector<int>,greater<int> > q;
    //降序队列,大顶堆
    priority_queue <int,vector<int>,less<int> >q;
    //greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
    

    具体操作为:
    借助 哈希表 来建立数字和其出现次数的映射,遍历一遍数组统计元素的频率
    维护一个元素数目为 kk 的最小堆
    每次都将新的元素与堆顶元素(堆中频率最小的元素)进行比较
    如果新的元素的频率比堆顶端的元素大,则弹出堆顶端的元素,将新的元素添加进堆中
    最终,堆中的 kk 个元素即为前 kk 个高频元素
    来源:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/leetcode-di-347-hao-wen-ti-qian-k-ge-gao-pin-yuan-/

    // 时间复杂度:O(nlogk)
    // 空间复杂度:O(n)
    class Solution {
    public:
        // 小顶堆
        class mycomparison {
        public:
            bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
                return lhs.second > rhs.second;
            }
        };
        vector<int> topKFrequent(vector<int>& nums, int k) {
            // 要统计元素出现频率
            unordered_map<int, int> map; // map<nums[i],对应出现的次数>
            for (int i = 0; i < nums.size(); i++) {
                map[nums[i]]++;
            }
    
            // 对频率排序
            // 定义一个小顶堆,大小为k
            priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
            
            // 用固定大小为k的小顶堆,扫面所有频率的数值 
            for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
                pri_que.push(*it);
                if (pri_que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                    pri_que.pop();
                }
            }
    
            // 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒叙来输出到数组
            vector<int> result(k);
            for (int i = k - 1; i >= 0; i--) {
                result[i] = pri_que.top().first;
                pri_que.pop();
            }
            return result;
    
        }
    };
    
  • 相关阅读:
    关于 Delphi 中的Sender和易混淆的概念(转)
    C#实现打印与打印预览功能(转)
    Quartz.NET
    如何从Powerdesigner进行数据建模并生成SQL脚本
    pentaho BI套件中PSW和PDI的连接
    Oracle中如何使用imp语言导入dmp文件
    DatePicker和DateEdit的区别
    dev控件中LookUpEdit的数据绑定问题
    如何在GridControl的某一列放入CheckBox、Button以及其他控件
    在GridControl中如何选中某一行中的某一列
  • 原文地址:https://www.cnblogs.com/ZigHello/p/14353532.html
Copyright © 2020-2023  润新知