[编程题] 基础:如何使用大顶堆和小顶堆找topN
需求
(1)我们如何从一个链表或者数组中,找到第k大的数,或者前k大的数。使用小顶堆。(输出是从小到大排列的前K大的数)
(2)我们如何从一个链表或者数组中,找到第k小的数,或者前k小的数(输出的堆是堆顶最大,其他不是序列顺序),使用大顶堆。
小顶堆
找到数组中第K大的元素
方法:需要找第K大,使用小顶堆。
Java代码:
package Demo11_堆;
import java.util.PriorityQueue;
/**
* @author jiyongjia
* @create 2020/7/26 - 11:27
* @descp:
*/
public class P1_小顶堆选出前K大 {
//默认是小顶堆
static int k=4;
static PriorityQueue<Integer> queue;
public static void main(String[] args) {
queue = new PriorityQueue<Integer>(k);
int[] arr = {1,3,5,2,6};
//把数组元素放入到堆中
for (int num:arr){
P1_小顶堆选出前K大.add(num);
}
}
//要求选出前k大的数
public static void add(int val){
if(queue.size()<k){
queue.offer(val);
//小顶堆的堆顶放的是已存在堆中的最下的数,如果有val比其最小的堆顶值大,说明堆中不是前k大的数,调整堆。
}else if(queue.size()>=k && queue.peek()<val){
queue.poll();
queue.offer(val);
}
System.out.println("数组中第"+k+"大:"+queue.peek()); //数组中第4大:2
System.out.println("堆:"+queue); //堆:[2, 3, 5, 6]
}
}
输出:第4大的元素是2,堆中的i情况是2 3 5 6
大顶堆
找到数组中第K小的元素
方法:需要找第K小,使用大顶堆。
注:要构造大顶堆的时候,是需要构造方法传入comparator比较器,compare方法的参数o2-o1表示大顶堆。o1-o2返回表示小顶堆,小顶堆也是默认的,可以无comparator。
Java代码:
package Demo11_堆;
import java.util.Comparator;
import java.util.Iterator;
import java.util.PriorityQueue;
/**
* @author jiyongjia
* @create 2020/7/26 - 11:54
* @descp:
*/
public class P2_大顶堆选出前K小 {
static PriorityQueue<Integer> queue;
static int k = 3;
public static void main(String[] args) {
queue = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1; //小顶堆o1-o2,大顶堆o2-o1;
}
});
int[] arr = {1,2,3,4,5,6,7,8};
//把数组元素放入到堆中
for (int num:arr){
P2_大顶堆选出前K小.add(num);
}
}
//要求选出前k小的数
public static void add(int val){
if(queue.size()<k){
queue.offer(val);
//大顶堆,堆顶放的是已存在堆中的最大的元素,如果存在val比堆中存在的最大元素小,说明堆中保存的不是前k小,去除堆顶,放入val
}else if(queue.size()>=k && queue.peek()>val){
queue.poll();
queue.offer(val);
}
System.out.println("第k小的元素:"+queue.peek());
System.out.println("堆中元素:"+queue);
}
}
输出: