例题1:数组中最小的k个数
思路:采用大根堆维护数组中的前k个最小的值。首先将k个数插入大根堆,然后从k+1个数开始遍历数组,遍历到比大根堆中堆顶的数要小的数值,就弹出堆顶的数,并插入当前遍历到的数。最后,将k个最小值存储到数组中返回即可。
class Solution {
public int[] smallestK(int[] arr, int k) {
int[] vec = new int[k];//创建一个数组存放k个元素
if (k == 0) {
return vec;
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {//大根堆需要用户提供比较器,采用Comparator接口,重写该接口中的compare方法
public int compare(Integer num1, Integer num2) {
return num2 - num1;
}
});
for (int i = 0; i < k; ++i) {//将k个数值放入大根堆
maxHeap.offer(arr[i]);
}
for (int i = k; i < arr.length; ++i) {
if (maxHeap.peek() > arr[i]) {//查看是否大于大根堆的堆顶元素
maxHeap.poll();//堆顶元素弹出
maxHeap.offer(arr[i]);//较小的值放入大根堆
}
}
for (int i = 0; i < k; ++i) {
vec[i] = maxHeap.poll();//将k个最小的数存储在数组中
}
return vec;
}
}
例题2:数组中第k大的数字
思路:找到k个最大的数字,其中最小的数字即为数组中第k大的数字。采用小根堆存储k个最大的数字,每次从数组中,然后判断数组中其他数字是否小于堆顶的最小值,如果新读入的数字比堆顶数字的值要大,那么就弹出堆顶数字,将新的数字入堆。
class KthLargest{
private PriorityQueue<Integer> minHeap;
private int size;
public KthLargest(int k, int[] nums){
size=k;
minHeap=new PriorityQueue<>();
for(int x: nums){//存储k个元素到小根堆
add(x);
}
}
public int add(int val){
if(minHeap.size()<size){//如果小根堆中的元素小于k个,加入新元素
minHeap.offer(val);
}else if(val>minHeap.peek()){//判断新读入的值是否比堆顶数字的值要大
minHeap.poll();
minHeap.offer(val);
}
return minHeap.peek();
}
}