347. 前 K 个高频元素
题目描述:
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
思路分析:
对我自己来说 , 首先我想到用一个map<int,int>,来记录 。first->是value , second->value元素出现的次数。
这样我们就收集到了整数数组每一个值出现的次数。那么我们处理收集到的数据 ?
采用优先级队列来进行数据处理 ,对于求前k个(对频率进行排序 -> 优先级队列)。
优先级队列底层是 堆,堆是一个完全二叉树,当然你也可以不用知道它是如何实现的 ,只要会用就可以了。
首先肯定会想到大顶堆 (根节点是最大值),但是我们这里只需要维护前k个元素 ,
当元素的个数大于k时 ,要进行出队操作,此时如果我们出队 ,是不是将最大的数据移除出去了?
所以这里我们采用小顶堆(根节点是最小值)。
优先级队列的元素是一个键值对 (pair<int ,int>),和我们的map是对应的 。
在入队的时候 ,比较的是map<int,int> 的second ,出现次数少的排在前面。我们需要自定义一个比较函数(对()进行重写)。
struct my_compare{
int operator()(const pair<int ,int>&a ,const pair<int ,int>&b){
return a.second > b.second;
}
};
当遍历完map中得所有元素,因为是小顶堆 ,前面的最小 ,后面的最大。
从后往前进行赋值 。
vector<int>ret( k ,0); //定义一个vector ,大小是 k 讲所有值初始化为 0
while(!my_priority_queue.empty()){
ret[--k]= my_priority_queue.top().first;
my_priority_queue.pop();
}
完整代码实现:
class Solution {
public:
struct my_compare{
int operator()(const pair<int ,int>&a ,const pair<int ,int>&b){
return a.second > b.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
map<int ,int>index; //first 是value seconed 是数量
//map ->记录每一个元素出现的个数
for(int i = 0;i<nums.size() ;i++){
index[nums[i]]+=1;
}
//优先队列 priority_queue 底层是二叉树
priority_queue<pair<int ,int> ,vector<pair<int ,int >>,my_compare>my_priority_queue;
for( auto temp: index){
my_priority_queue.push(temp);
if(my_priority_queue.size() >k ){
my_priority_queue.pop(); //出队 ,我们只需要维护k个元素
}
}
vector<int>ret( k ,0);
while(!my_priority_queue.empty()){
ret[--k]= my_priority_queue.top().first; //获取对头元素 ,拿到键值对的 value
my_priority_queue.pop(); //出队
}
return ret;
}
};