[編程題] 基礎:如何使用大頂堆和小頂堆找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);
}
}
輸出: