347. 前 K 个高频元素

题目描述:

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

 

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]
 

提示:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。

 

思想:

思路一:使用hashmap统计nums中数字的出现次数,然后按value进行排序,返回前k项,注意map的排序要借助vector,时间复杂度与空间复杂度较高

思路二:

  • 利用hashmap统计元素出现的频次,建立元素与频次之间的映射
  • 创建元素个数为k的小顶堆优先队列
  • 遍历hashmap, 当优先队列中元素个数小于k时,直接加入优先队列
  • 如果优先队列中元素个数等于k时,新元素的频次与堆顶元素频次比较,如果比堆顶元素频次高,pop出堆顶元素,然后再push新的元素,如果比堆顶元素频次还要低,则不处理
  • 最后使用数组保存频次前k的元素

 

思路一代码:

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int,int>m;
        for(auto num : nums)    //  存到哈希结构里
            m[num]++;
        vector<pair<int,int >>v;
        vector<int>ans;
        for(auto it : m)        //  存到用于对value排序的容器里
            v.push_back(make_pair(it.first,it.second));
        sort(v.begin(),v.end(),[](pair<int,int> &a,pair<int,int> &b)->bool{return a.second>b.second;});
        //  对容器中的pair按照出现次数从大到小排序
        /*
            C++ 的lambda表达式和java的略有区别
        */
        for(int i=0;k;++i,--k)
            ans.push_back(v[i].first);

        return ans;
    }
};

思路二代码:

class Solution {
    public:
        struct cmp {
            bool operator()(const pair<int, int> &left, const pair<int, int> &right) 
            {
                return left.second > right.second;
            }
        };

        vector<int> topKFrequent(vector<int>& nums, int k) {
            unordered_map<int, int> mp;
            for (auto i : nums) {
                mp[i]++;
            }
            
            priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q; // 创建一个小顶堆
            
            for (auto item : mp) {
                if (q.size() < k) {
                    q.push(item);
                } else if (item.second > q.top().second) {
                    q.pop();
                    q.push(item);
                }
                // 新的元素频次小于堆顶元素频次的元素不处理。
            }
            
            vector<int> res(q.size(), 0);
            
            while (!q.empty()) {
                res[q.size()-1] = q.top().first;
                q.pop();
            }
            
            return res;
        };
};
posted @ 2020-05-06 21:34  thefatcat  阅读(115)  评论(0)    收藏  举报