堆是一个完全二叉树。堆中每个节点大于或等于左右子节点(大根堆),小根堆相反。即大根堆最大元素在堆顶,小根堆最小元素在堆顶。
堆使用数组存储
堆常用于解决topK问题
例题1:215. 数组中的第K个最大元素
class Solution {
public int findKthLargest(int[] nums, int k) {
//小根堆size=k,则堆顶就是第k个大的元素。
Queue<Integer> qp=new PriorityQueue<>((v1,v2)->v1 - v2);//默认小根堆
for(int i:nums){
if(qp.size()<k)
qp.offer(i);
else if(qp.peek()<i){//如果加入的比堆顶还小,不用加
qp.poll();
qp.offer(i);
}
}
return qp.peek();//返回堆顶
}
}
如何定义一个堆:
Queue<Integer> qp=new PriorityQueue<>() 默认是小根堆
定义一个大根堆:
Queue<Integer> qp=new PriorityQueue<>((v1,v2)->v2 - v1);
例题2:347. 前 K 个高频元素
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map=new HashMap<>();
//先对数字频率进行记录
for(int i:nums){
map.put(i,map.getOrDefault(i,0)+1);
}
//小根堆。(将小根堆前面的元素去掉,就得到了高频元素。)
Queue<Integer> qp=new PriorityQueue<>((v1,v2)->map.get(v1)-map.get(v2));
//lambda表达式遍历哈希表,key,value.
map.forEach((num,value) ->{
if(qp.size()<k){//小根堆内存没满。
qp.offer(num);//加入就完事了
}
else if(map.get(qp.peek())<value){//小根堆满了,如果小根堆堆顶元素出现的次数还比该num的次数还少,将堆顶元素踢出。
qp.poll();
qp.offer(num);
}
});
int[] arr=new int[k];
for(int i=0;i<arr.length;i++){
arr[i]=qp.poll();
}
return arr;
}
}
①哈希表记录数字频率:
map.put(i,map.getOrDefault(i,0)+1);
②遍历哈希表,lambda表达式:
map.forEach( (key, value) -> {
//method
});