【力扣hot100题】(074)前 K 个高频元素
和上一题的堆排序差不多,这题稍微绕了一些。
其实方法不固定,我的做法是先将vector去重顺便用hash记录每个元素出现的次数,接着构建大根堆,然后遍历k次,每次将根节点与最后一个值替换,然后根据前面的值重新调整大根堆,遍历完后删除前面的节点。
class Solution {
public:
unordered_map<int,int> freq;
void adjustheap(vector<int>& nums,int root,int size){
int left=root*2+1;
int right=root*2+2;
int maxx=root;
if(left<size&&freq[nums[left]]>freq[nums[maxx]]) maxx=left;
if(right<size&&freq[nums[right]]>freq[nums[maxx]]) maxx=right;
if(maxx!=root){
swap(nums[maxx],nums[root]);
adjustheap(nums,maxx,size);
}
}
void initheap(vector<int>& nums){
for(int i=freq.size()/2-1;i>=0;i--) adjustheap(nums,i,nums.size());
}
vector<int> topKFrequent(vector<int>& nums, int k) {
for(int i=0;i<nums.size();i++){
if(freq.find(nums[i])!=freq.end()){
freq[nums[i]]++;
nums.erase(nums.begin()+i);
i--;
}
else freq[nums[i]]=1;
}
initheap(nums);
int size=nums.size();
for(int i=0;i<k;i++){
swap(nums[0],nums[size-1]);
size--;
adjustheap(nums,0,size);
}
nums.erase(nums.begin(),nums.begin()+size);
return nums;
}
};
顺便学了一个优先队列(其内部是用堆实现的),学习了一下优先队列怎么自定义排序函数,需要建立一个比较函数(在class中要加static),因为priority_queue的比较函数需要一个不依赖任何class类实例的函数。
并且将pair作为优先队列中的元素使用时,加入元素可以使用q.insert({first,second}),也可以用更方便的q.emplace(first,second)不用加大括号,因为emplace是直接在队列中构造pair,而insert需要先构建一个pair再放入队列。
另外还有priority_queue的初始化问题,priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(&compare)> q(compare);中三个参数分别代表队列中元素类型、底层容器(可以选择vector和deque)、比较函数(需要使用decltype将函数转化成所需要类型)。
class Solution {
public:
static bool compare(pair<int,int>& a,pair<int,int>& b){
return a.second>b.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> freq;
for(auto& v:nums) freq[v]++;
priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(&compare)> q(compare);
for(auto& [num,count]:freq){
if(q.size()<k) q.emplace(num,count);
else if(q.top().second<count){
q.emplace(num,count);
q.pop();
}
}
vector<int> result;
while(!q.empty()){
result.push_back(q.top().first);
q.pop();
}
return result;
}
};