文章目录
题目
方法一:优先队列(基于大顶堆实现)
PriorityQueue<int[]> queue = new PriorityQueue<>((a,b)->b[1]-a[1]);
优先队列 按照队列中的数组的第二个元素从大到小排序
((a,b)->b[1]-a[1])
class Solution {
//基于大顶堆实现
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)
PriorityQueue<int[]> queue = new PriorityQueue<>((a,b)->b[1]-a[1]);
for(int num : nums)
map.put(num,map.getOrDefault(num,0)+1);
//将map集合中的 key(num) value(出现次数) 以数组的形式 a[key , value] 加入到优选队列中
///按照value从大到小的顺序进行排列
for(Map.Entry<Integer,Integer> entry :map.entrySet())
queue.add(new int[]{entry.getKey(),entry.getValue()});
//取出优先队列(已经按照value按从大到小排序好了)排在前k位的(key)到结果数组
int[] res = new int[k];
for(int i = 0 ; i < k ; i++){
res[i] = queue.poll()[0];
}
return res;
}
}
方法二:优先队列(基于小顶堆实现,队列只需维护k个元素)
PriorityQueue<int[]> queue = new PriorityQueue<>((a,b)->a[1]-b[1]);
优先队列 按照队列中的数组的第二个元素从小到大排序
((a,b)->a[1]-b[1])
class Solution {
//基于小顶堆实现
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//出现次数按从队头到队尾的顺序是从小到大排,出现次数最多的在队头(相当于大顶堆)
PriorityQueue<int[]> queue = new PriorityQueue<>((a,b)->a[1]-b[1]);
for(int num : nums)
map.put(num,map.getOrDefault(num,0)+1);
//将map集合中的 key(num) value(出现次数) 以数组的形式 a[key , value] 加入到优选队列中
///按照value从大到小的顺序进行排列
for(Map.Entry<Integer,Integer> entry :map.entrySet()){//小顶堆只需要维持k个元素有序
//如果队列大小小于k 直接将 a[key , value]加入队列
if(queue.size() < k) queue.offer(new int[]{entry.getKey(),entry.getValue()});
//如果队列大小为k 则需要判断当前对列队首的数组 value(次数) 和 entry.getValue()对比 如果大于队首的value 则替换队首元素,否则不做改变
else if(entry.getValue() > queue.peek()[1]){
queue.poll();
queue.offer(new int[]{entry.getKey(),entry.getValue()});
}
}
int[] res = new int[k];
//由于优先队列时小根堆,所以出现次数大的出现在队列对后面 需要逆序把队列中的key 放到结果数组中
for(int i = k-1 ; i >=0 ; i--)
res[i] = queue.poll()[0];
return res;
}
}