##菜鸟刷题(3)【堆 ToK Elements问题】
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
方法一:直接调Arrays.sort()就可以做出来
方法二:利用优先队列PriorityQueue,默认是小顶堆(完全二叉树,根节点是最小的)
代码:
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> heap=new PriorityQueue<>();
for(int num:nums){
heap.add(num);
if(heap.size()>k){//始终保存队列中只有k个元素
//那么最终根节点就是第k大的数
heap.poll();//根节点出队
}
}
return heap.peek();//返回根节点的值
}
}
tips:
PriorityQueue<Integer> heap=new PriorityQueue<>();默认是小顶堆。
如果想要大顶堆,则代码:PriorityQueue<Integer> heap=new PriorityQueue<>((a,b)->b-a);
指定队列大小为k,则代码:PriorityQueue<Integer> heap=new PriorityQueue<>(k,(a,b)->b-a);
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
代码:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//计算频率
Map<Integer,Integer> map=new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<Integer> heap=new PriorityQueue<>((a,b)->map.get(a)-map.get(b));//非常关键的重写,实现key的频率的小顶堆
for(int key:map.keySet()){
heap.add(key);
if(heap.size()>k){//这里就同上面一题差不多,始终保持队列中只有k个元素
heap.poll();
}
}
int[] ans=new int[k];
for(int i=0;i<k;i++){
ans[i]=heap.poll();
}
return ans;
}
}
关键代码:
实现频率的计算:
map.put(num,map.getOrDefault(num,0)+1);
Map.getOrDefault(Object key, V defaultValue)方法的作用是:
当Map集合中有这个key时,就使用这个key值;
如果没有就使用默认值defaultValue。
实现key的频率的小顶堆:
PriorityQueue<Integer> heap=new PriorityQueue<>((a,b)->map.get(a)-map.get(b));