当前位置: 首页 > news >正文

优先级队列 2

1、常用接口介绍

1.1 PriorityQueue的特性

        Java集合框架中提供了 PriorityQueue PriorityBlockingQueue 两种类型的优先级队列, PriorityQueue 是线 程不安全的, PriorityBlockingQueue 是线程安全的 ,这里主要介绍PriorityQueue。

        关于PriorityQueue的使用要注意: 

        1. 使用时必须导入PriorityQueue所在的包,即:

        2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常,如下图: 

        3. 不能插入null对象,否则会抛出NullPointerException。 

        4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容。

        5.插入和删除元素的时间复杂度为O(log2N)。

        6.底层使用的是堆结构。

        7.其默认情况下是小根堆 --> 即每次获得到的元素第是最小的元素。

1.2 PriorityQueue常用接口介绍 

1.2.1 优先级队列的构造

        在IDEA中的PriorityQueue的Structure中可以看到PriorityQueue有多种构造方法。 

 

        这里先做了解,后面会详细讲解。

        总结:

         注意:默认情况下,PriorityQueue队列是小堆,如果需要大堆需要用户提供比较。 

class IntCmp implements Comparator<Integer> {

    @Override
    public int compare(Integer o1, Integer o2) {
        return o2.compareTo(o1);
    }
}
public class Test {
    //找第k大的元素就是小根堆的堆的堆顶元素
    //找第k小就是大根堆的堆顶元素
    public static void main(String[] args) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new IntCmp());
        priorityQueue.offer(12);
        priorityQueue.offer(23);
        priorityQueue.offer(34);
        priorityQueue.offer(45);
        System.out.println(priorityQueue);
    }
}

1.2.2 插入/删除/获取优先级最高的元素 

        下图是方法名和使用方法:

        优先级队列的扩容: 

1.2.3 面试题 17.14. 最小K个数 - 力扣(LeetCode)

        Top-k问题:求当前数据中最大或者最小的k个数据,一般来说数据量都比较大。比如:学校的前3名、全球富豪排行榜前100名、世界500强企业.......

        做法1:把数组排序 排序之后 去除前10个最大的。但是当数据量非常大的时候,你无法在内存中进行排序。

        做法2:把所有数据放到优先级队列中,出队k次就ok了。但是当数据量非常大的时候,你无法放到优先级队列中。

class Solution {
    public int[] smallestK(int[] arr, int k) {
         int[] ret = new int[k];
        if(arr == null || k <= 0){
             return ret;
       }
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(arr.length);
         for (int i = 0; i < arr.length; i++) {
          priorityQueue.offer(arr[i]);
        }
         for (int i = 0; i < k; i++) {
           ret[i] = priorityQueue.poll();
         }
         return  ret;

        我们建议的做法:

        假设找前K个最大的数据,用前K个元素建小根堆K(堆顶就是这K个元素里面的最小值了)  建一个i下标遍历剩余数组,如果i下标的元素大于堆顶元素,那么说明堆顶元素一定不是前K个最大的元素之一 ,把剩下的元素每次与堆顶元素比较,把堆顶元素出队,再把i下标的元素入队。(找前K个最小的数据,则与上面相反要建立大根堆)。

        上面OJ链接的代码:(因为是建立大根堆,所以需要创建一个比较器)

class ICompare implements Comparator<Integer>{
    public int compare(Integer o1,Integer o2){
        return o2.compareTo(o1);
    }
}
class Solution {
    public int[] smallestK(int[] arr, int k) {
        int[] ret = new int[k];
        //如果不判断,后面优先级队列会产生空指针异常
        if(k==0){
            return ret;
        }
     PriorityQueue<Integer> priorityqueue = new PriorityQueue<>(new ICompare());
     //先将K个元素放入优先级队列中
     for(int i = 0;i < k;i++){
        priorityqueue.offer(arr[i]);
     }
     //将k后面的元素和 堆顶元素比较
     for(int i = k; i < arr.length;i++){
        if(arr[i] < priorityqueue.peek()){//说明当前堆顶的元素不是最小的k个数
                priorityqueue.poll();
                priorityqueue.offer(arr[i]);
        }
     }
     //出k个元素
     for(int i = 0;i < k; i++){
           ret[i] = priorityqueue.poll();
     }
     return ret;
    }
}

        下面是找到最大K个数的代码,可供大家参考:

    public static int[] maxestK(int[] arr, int k) {
        int[] ret = new int[k];
        if(arr == null || k <= 0){
            return ret;
        }
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(arr.length);
        //先放k个元素进小根堆
        for (int i = 0; i < k; i++) {
            priorityQueue.offer(arr[i]);
        }
        //遍历剩下的元素
        for (int i = k; i < arr.length; i++) {
            int top = priorityQueue.peek();
            if(arr[i] > top){
                priorityQueue.poll();
                priorityQueue.offer(arr[i]);
            }
        }
        for (int i = 0; i < k; i++) {
         ret[i] = priorityQueue.poll();
        }
        return ret;
    }

相关文章:

  • 【JavaEE】网络编程socket
  • 【面试中的分布式定时任务】
  • 上海亚商投顾:沪指窄幅震荡 深海科技概念持续活跃
  • 封装一个分割线组件
  • 【C#】Winform调用NModbus实现Modbus TCP 主站通讯
  • QT Quick(C++)跨平台应用程序项目实战教程 2 — 环境搭建和项目创建
  • 批量删除 PPT 空白幻灯片页面
  • 【系统架构设计师】操作系统 - 特殊操作系统 ③ ( 微内核操作系统 | 单体内核 操作系统 | 内核态 | 用户态 | 单体内核 与 微内核 对比 )
  • 霍尔传感器与电流互感器的区别
  • 校园论坛系统自动化测试报告
  • 看盘细节系列 篇四:集合竞价低开3%以上
  • Cursor的使用感受,帮你使用好自动化编程工具,整理笔记
  • vscode查看文件历史git commit记录
  • FPGA中级项目5——VGA part1
  • idea集成git
  • C++学习之QT实现取证小软件首页
  • 汇能感知高品质的多光谱相机VSC02UA
  • jmeter将返回的数据写入csv文件
  • CCF-CSP第25次认证第二题——出行计划【NA!重难点在于理解为什么答案是 cnt1−cnt2】
  • 【开源宝藏】30天学会CSS - DAY3 第三课 滑动文本+变色
  • 买新房可申领学位,广州南沙出台购房入学政策
  • 黄仁勋访华期间表示希望继续与中国合作,贸促会回应
  • 著名统计学家、北京工业大学应用数理学院首任院长王松桂逝世
  • 秦洪看盘|短线热点降温,A股回落整固
  • 破解160年基因谜题,我国科学家补上豌豆遗传研究最后拼图
  • 好未来:2025财年收入增长51%,下个财年提高整体盈利能力是首要任务