【leetcode】【medium】347. Top K Frequent Elements

347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements.

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Example 2:

Input: nums = [1], k = 1
Output: [1]

Note:

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

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

思路

总体的思路是:先统计,再排序,输出。

法一:排序算法

时间复杂度O(nlogn):

统计:O(n)。hash表查找O(1),++操作O(1),共n个元素。

排序:排序最低复杂度O(nlogn)。

扫描二维码关注公众号,回复: 9440658 查看本文章

输出:O(n)。

这是通常思路,可以看出瓶颈在排序算法这里。

这个实现就不写了。

法二:优先队列维护k个元素

在统计好之后,使用优先队列维护k个元素,若新频率比队列中最小频率大时,弹出最小,插入新频率。

调整新插入元素的位置:O(logk),故算法时间复杂度为O(nlogk),当k<<n时有较大提升。

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> res;
        if(nums.size()<=0 || k<=0) return res;
        unordered_map<int,int> freq;
        for(int num: nums){
            ++freq[num];
        }
        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> que;
        for(unordered_map<int,int>::iterator it=freq.begin(); it!=freq.end(); ++it){
            if(que.size()<k) que.push(make_pair(it->second, it->first));
            else{
                auto tmp = que.top();
                if(tmp.first<it->second){
                    que.pop();
                    que.push(make_pair(it->second, it->first));
                }
            }
        }
        while(!que.empty()){
            res.push_back(que.top().second);
            que.pop();
        }
        return res;
    }
};

法三:优先队列维护(n-k)个元素

优先队列不维护topk大的,改去维护剩下较小的元素,因此只要是被从队列被挤出来/挤不进的元素,就可以直接输出。

法二在n和k差不多大时没啥提升,而本法在这种情况下能有很好的优化效果。

注意:(n-k)不一定为正数,<=0时都是输出所有数据。这点需要在弹出队列时加一个判断。

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> res;
        if(nums.size()<=0 || k<=0) return res;
        unordered_map<int,int> freq;
        for(int num: nums){
            ++freq[num];
        }
        priority_queue<pair<int,int>, vector<pair<int,int>>, less<pair<int,int>>> que;
        int len = freq.size()-k;
        for(unordered_map<int,int>::iterator it=freq.begin(); it!=freq.end(); ++it){
            if(que.size()<len) que.push(make_pair(it->second, it->first));
            else{
                if(que.empty()) res.push_back(it->first);
                else{
                    auto tmp = que.top();
                    if(tmp.first>it->second){
                        res.push_back(tmp.second);
                        que.pop();
                        que.push(make_pair(it->second, it->first));
                    }else res.push_back(it->first);
                }
            }
        }
        return res;
    }
};
发布了127 篇原创文章 · 获赞 2 · 访问量 3755

猜你喜欢

转载自blog.csdn.net/lemonade13/article/details/104372409