思路一
hashmap + minheap
维护一个最小堆,堆顶元素的频率是整个堆中最的。
- 如果堆未满的话,直接往堆中添加元素
- 如果对已满,那就把要添加的元素的频率与堆中频率最小的元素进行比较,如果要比较的元素频率大于堆顶,则添加,否则不添加
- 按照条件二,遍历map中所有的Entry后
- 遍历完整个频率map后,最小堆中则维护着频率最大的k个entry
- 遍历优先级队列,然后取出优先级队列中Entry 中的getKey()即可
hashmap统计频率,minheap从中选择k个最大的元素元素,
代码(java)
class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
//统计频率的写法,
for(int n:nums){
map.put(n,map.getOrDefault(n,0) + 1);
}
Queue<Map.Entry<Integer,Integer>> minheap = new PriorityQueue<>(k,(a,b)->(a.getValue()-b.getValue()));
//k为堆的容量大小,
for(Map.Entry<Integer,Integer> entry: map.entrySet()){
//逐渐构建堆的过程,如果堆中的元素比较少于k个,直接添加
if(minheap.size()<k)
minheap.add(entry);
else{
Map.Entry<Integer,Integer> min = minheap.peek();
if(entry.getValue()>min.getValue())
{
minheap.poll();
minheap.add(entry);
}
}
}
List<Integer> res =new ArrayList<>();
while(!minheap.isEmpty()){
Map.Entry<Integer,Integer> entry = minheap.poll();
res.add(entry.getKey());
}
return res;
}
}
c++
typedef pair<int, int> P;
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
for (int x : nums) cnt[x] ++;
priority_queue<P, vector<P>, greater<P> > q;
for (auto &x : cnt) {
if (q.size() < k)
q.push(make_pair(x.second, x.first));
else {
if (q.top().first < x.second) {
q.pop();
q.push(make_pair(x.second, x.first));
}
}
}
vector<int> ans;
while (!q.empty()) {
ans.push_back(q.top().second);
q.pop();
}
return ans;
}
};
时间复杂度
O(logK)