使用优先队列解决LeetCode347前K个高频元素
优先队列也是队列,不同于普通队列是队头队尾元素进行出队和入队的操作,优先队列是寻找队列中的最大值或者最小值来进行操作。
优先队列的底层实现是堆。对于堆要熟悉到白板编程的程度。
C++中的优秀队列容器是priority_queue.
#include<iostream>
#include<queue>
#include<ctime>
using namespace std;
bool myCmp(int a,int b){
return a%10<b%10; //比较两个数的个位数,个位数大的排在前面
}
int main(){
srand(time(NULL)); //随机数种子
priority_queue<int> pq; //以最大堆为底层的优先队列
for(int i=0;i<10;i++){
int num = rand()%100;
pq.push(num);
cout<<"insert"<<num<<"in priority queue."<<endl;
}
while(!pq.empty()){
cout<<pq.top()<<" ";
pq.pop();
}
cout<<endl<<endl;
priority_queue<int,vector<int>,greater<int>> pq2; //以最小堆为底层的优先队列
for(int i=0;i<10;i++){
int num = rand()%100;
pq2.push(num);
cout<<"insert"<<num<<"in priority queue."<<endl;
}
while(!pq2.empty()){
cout<<pq2.top()<<" ";
pq2.pop();
}
priority_queue<int,vector<int>,function<bool(int,int)>> pq3(myCmp); //自定义比较函数
for(int i=0;i<10;i++){
int num = rand()%100;
pq3.push(num);
cout<<"insert"<<num<<"in priority queue."<<endl;
}
while(!pq3.empty()){
cout<<pq3.top()<<" ";
pq3.pop();
}
return 0;
}
leetcode347
算法思路:维护一个含有K个元素的优先队列,如果遍历到的元素比队列中最小频率元素的频率高,则取出队列中最小频率的元素,将新元素入队。最终,队列中剩下的,就是前k个出现频率最高的元素。此时算法的时间复杂度是O(nlogk)
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
//统计每个元素出现的频率
unordered_map<int,int> freq;
for(int i=0;i<nums.size();i++){
freq[nums[i]]++;
}
//扫描数组,维护当前出现频率最高的k个元素
//优先队列中,按照频率排序,所以数据对是(频率,元素)的形式
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>> > pq;
for(unordered_map<int,int>::iterator iter=freq.begin();iter!=freq.end();iter++){
if(pq.size()==k){
//unordered_map中频率在second,优先队列中频率在first
if(iter->second > pq.top().first){
pq.pop();
pq.push(make_pair(iter->second,iter->first));
}
}
else
pq.push(make_pair(iter->second,iter->first));
}
vector<int> res;
while(!pq.empty()){
res.push_back(pq.top().second);
pq.pop();
}
return res;
}
};