力扣347. 前 K 个高频元素

题目来源(力扣):

https://leetcode.cn/problems/top-k-frequent-elements/description/

题目描述:

找到一个数组中前k个出现频率高的数。
1 <= nums.length <= 10^5
k 的取值范围是 [1, 数组中不相同的元素的个数]

基本思路:

最直观的方式就是记录数组中出现了哪些数字,以及各个数字出现的次数,最后利用排序算法例如快速排序sort一遍,打印前k个即可。
优化的方式就是,维护一个大小为k的优先队列,而非使用sort。
具体实现可以使用到map、结构体、快排等知识,这里只给出2种写法,以供参考。

写法1

哈希表+结构体快排

class Solution {
public:
    struct oo{
        int val;
        int tot;
    };
    vector<oo>a;    //下标从1开始便于操作
    unordered_map<int,int>index;//将nums中的数字映射到a中
    static bool cmp(oo X,oo Y){
        return X.tot>Y.tot;
    }
    vector<int> topKFrequent(vector<int>& nums, int k) {
        oo tmp;
        a.push_back(tmp);  //从下标1开始便于操作
        for(int i=0;i<nums.size();i++){
            int ind=index[nums[i]];
            if(ind==0){
                tmp.val=nums[i];
                tmp.tot=1;
                index[nums[i]]=a.size();
                a.push_back(tmp);
            }
            else {
                a[ind].tot++;
            }
        }
        sort(a.begin()+1,a.end(),cmp);
        // for(int i=1;i<a.size();i++)
        //     cout<<a[i].val<<" : "<<a[i].tot<<endl;
        vector<int>ans;
        for(int i=1;i<=k;i++){
            ans.push_back(a[i].val);
        }

        return ans;
    }
};
写法2

哈希表+优先队列
参考《代码随想录》如下,

class Solution
{
public:
    class cmp
    {
    public:
        bool operator()(const pair<int, int> &A, const pair<int, int> &B)
        { //根据q.second(即元素出现的次数)的大小来制定优先队列,一定是小根堆,这样子每次弹出的才是出现频率较小数
            return A.second > B.second;
        }
    };
    unordered_map<int, int> mmp;   //统计元素出现的次数
    vector<int> ans;
    vector<int> topKFrequent(vector<int> &nums, int k)
    {
        for (auto num : nums)
        {
            mmp[num]++;
        }
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> q;
        for (auto it = mmp.begin(); it != mmp.end(); it++)
        {
            q.push(*it);
            if (q.size() > k)
            { // 大小为k的优先队列
                q.pop();
            }
        }
        while (q.size())
        {
            //cout << q.top().second << endl;
            ans.push_back(q.top().first);
            q.pop();
        }
        return ans;
    }
};

时间复杂度

写法1为O(nlogn),写法2为O(nlogk) ,n为数组大小,k为数组中不同元素的个数

posted @ 2024-11-01 17:46  HB_Computer  阅读(51)  评论(0)    收藏  举报