[编程题] 基础:如何使用大顶堆和小顶堆找topN

[编程题] 基础:如何使用大顶堆和小顶堆找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

image-20200726121613963

大顶堆

找到数组中第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);

    }
}

输出:

image-20200726122033811

posted @ 2020-07-26 12:23  北鼻coder  阅读(1226)  评论(0编辑  收藏  举报