一、什么是堆?
堆是一种非线性结构,可以把堆看作一棵二叉树,也可以看作一个数组,即:堆就是利用完全二叉树的结构来维护的一维数组。
堆可以分为大顶堆和小顶堆。
大顶堆:每个结点的值都大于或等于其左右孩子结点的值。
小顶堆:每个结点的值都小于或等于其左右孩子结点的值。
如果是排序,求升序用大顶堆,求降序用小顶堆。
一般我们说 topK 问题,就可以用大顶堆或小顶堆来实现,
最大的 K 个:小顶堆
最小的 K 个:大顶堆这里是引用
二、PriorityQueue
常用的方法:
大根堆的构造
PriorityQueue<Integer> q = new PriorityQueue<>((o1,o2)->o2.compareTo(o1))
小根堆的构造
PriorityQueue<Integer> q = new PriorityQueue<>((o1,o2)->o1.compareTo(o2))
思考:首先能够想到的是求一个数组中前k个最小的数,并返回到该数组中。直接对该数组进行排序:Arrays.sort(input); 然后遍历前k个存入到res中,返回即可。但这样其实时间复杂读更高,既然是TopK的问题,我们不难想到用小顶堆的方式。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<Integer>();
// 排除特殊情况
if(k == 0||input.length==0) return res;
// 大根堆
PriorityQueue<Integer> q = new PriorityQueue<>((o1,o2)->o2.compareTo(o1));
// 创建一个k个大小的堆
for(int i = 0;i<k;i++){
q.add(input[i]);
}
for(int i = k;i<input.length;i++){
if(q.peek()>input[i]){
q.poll();
q.add(input[i]);
}
}
// 堆中元素取出入数组
for(int i =0;i<k;i++){
res.add(q.poll());
}
return res;
}