347. 前 K 个高频元素

125 阅读1分钟

难度: 中等

本节获得

  • 构建任意数据结构大小根堆
const static bool cmp(const pair<int,int>&a,const pair<int,int>&b){ //比较函数
    return a.first>b.first; //小根堆
}
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)>q(cmp);//创建自定义排序的小根堆
priority_queue<Type,contain,function>q;
  • 遍历键值对Map
for(auto &[a,b] : num){}//a是键,b是值

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例1

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

提出时间复杂度小与O(nlog(n))的算法

解题思路

  • 预处理每个元素出现的次数

  • 用一个小根堆依次存入元素以及出现次数,(a,b),a表示元素出现的次数,b表示元素值

  • 分两种情况考虑

    • 当堆内元素个数小与k时,此时任何元素均可入栈,元素以及其出现的次数压入堆内
    • 当堆内元素个数大于等于k时,

    (1)比较小根堆内元素出现次数是否比待入堆元素出现次数大

    (2)不大,则排出堆顶元素,如新元素

    (3)大,则舍弃当前待入堆元素

  • 最后堆内元素为k个,将其导入返回数组,算法结束。

class Solution {
public:
    const static bool cmp(const pair<int,int>&a,const pair<int,int>&b){
        return a.first>b.first;
    }
    vector<int> topKFrequent(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>ans(k,0);
        priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)>q(cmp);
        unordered_map<int,int>num;
        for(int i=0;i<n;i++){
            num[nums[i]]++;
        }
        for(auto &[a,b] : num){
            if(q.size()<k)q.push(make_pair(b,a));
            else if(q.top().first<b){
                q.pop();q.push(make_pair(b,a));
            }
        }
        int index=0;
        while(!q.empty()){
            auto a=q.top();q.pop();
            ans[index++]=a.second;
        }
        return ans;
    }
};

算法复杂度

算法时间复杂度:O(nlog(k))<O(nlog(n))

算法空间复杂度:O(n)