题目:给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
思路:使用map记录nums数组中的元素以及对应出现的次数。
使用优先队列PriorityQueue构造一个k个元素的小顶堆,记录出现频率最高的前k个元素,小顶堆的根记录了优先队列的k个元素中出现频次最少的元素。遍历map,若优先队列元素不足k个,则押入元素;若优先队列元素已为k个,且元素频次大于根元素频次,则弹出根元素,把该元素入队。最后优先队列中的顺序为出现频次递增的前K个高频元素。
若用优先队列构造一个大顶堆实现,则需对map中的所有元素对进行排序,使用小顶堆只需要维护k个元素对,故大顶堆性能没有小顶堆好。
代码:
public int[] topKFrequent(int[] nums, int k) {
//构建nums的哈希表
Map<Integer,Integer> map=new HashMap<>();
for(int i:nums){
map.put(i,map.getOrDefault(i,0)+1);
}
//使用优先队列获取出现频率前k高的元素,用小顶堆(根为记录的k个元素中出现次数最少的),优先队列存储二元组(元素,频次)
PriorityQueue<int[]> queue=new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
if(queue.size()<k){
queue.add(new int[]{entry.getKey(),entry.getValue()});
}
else{
if(entry.getValue()>queue.peek()[1]){
queue.poll();
queue.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] result=new int[k];
for(int i=k-1;i>=0;i--){
result[i]=queue.poll()[0];
}
return result;
}