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

  • 相关阅读:
    [SDOI2016]排列计数
    Broken robot
    环路运输
    naptime
    Accumulation Degree
    选课
    没有上司的舞会
    金字塔
    Polygon
    石子合并
  • 原文地址:https://www.cnblogs.com/jiyongjia/p/13379959.html
Copyright © 2020-2023  润新知