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

优先级队列(PriorityQueue 和 Top-K问题)

一、PriorityQueue

  java中提供了两种优先级队列:PriorityQueue 和 PriorityBlockingQueue。其中 PriorityQueue 是线程不安全的,PriorityBolckingQueue 是线程安全的。

  PriorityQueue 使用的是堆,且默认情况下是小堆——每次获取到的元素都是最小的元素。

  

1. 使用方法

(1)导入包: import java.util.PriorityQueue

(2)要求传入的元素具备比较大小的能力:Comparable | Comparator

(3)不能传入 null,否则会抛出NullPointerException异常

(4)因为默认为小堆,所以优先级最高的元素为最小的元素。若希望优先级最高的元素为最大的元素,则需要使用大堆,即需要用户提供比较器(将比较器对象作为参数传入其构造函数)

2. 内部方法:

(1)构造方法:

PriorityQueue():创建一个空的优先级队列,默认容量为11

PriorityQueue(int  initialCapacity):创建一个初始容量为 initialCapacity 的优先级队列

PriorityQueue(Collection<? extends E>  c):用一个集合来创建优先级队列

如:PriorityQueue<Integer> q = new PriorityQueue<>(list);

(2)常用方法:

① boolean offer(E  e):插入元素 e   O(log(n))

② E peek():获取优先级最高的元素,若优先级队列为空,返回null

③ E poll():删除优先级最高的元素并将其返回,若队列为空,返回null    O(log(n))

④ int  size():获取有效元素的个数

⑤ void clear():清空

⑥ boolean  isEmpty():判断优先级队列是否为空

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

  • 当容量小于 64 时,按照 oldCapacity 的 2 倍扩容
  • 当容量大于 64 时,按照 oldCapacity 的 1.5 倍扩容
  • 当容量超过 MAX_ARRAY_SIZE 时,按照 MAX_ARRAY_SIZE 扩容

二、Top-K问题   

  Top-K问题:在一组数据中,找到最大(最小)的 K 个数。

  不需要对所有数据进行排序,只需要找到符合要求的 K 个数,然后将这 K 个数再进行排序

  如何用堆去解决 Top-K 问题:

假设要在海量数据中找到最大的 K 个数:

(1)要找最大的:建小堆。(因为后序需要用堆顶元素跟其他元素进行比较)

(2)该小堆的最大容量为 K

(3)把剩下的元素挨个和堆顶元素(K个中最小的)进行比较

如果 元素 <= 堆顶元素 : 该元素一定不是最大个K个元素中的元素

如果 元素 > 堆顶元素 :该元素是候选人,用该元素替代堆顶元素 + 向下调整。

  代码的实现可以分两种:直接使用 PriorityQueue 优先级队列、不使用 PriorityQueue 即自己实现其内部的堆。

面试题 17.14. 最小K个数

代码一:直接使用 PriorityQueue 优先级队列以及删除、添加的方法。

class Solution {//因为最小的 k 个数,所以需要建大堆static class IntegerComparator implements Comparator<Integer> {public int compare(Integer o1, Integer o2) {//重写比大小的规则return o2 - o1;}}public int[] smallestK(int[] arr, int k) {//考虑 k == 0if (k == 0) {return new int[0];}Comparator<Integer> c = new IntegerComparator();PriorityQueue<Integer> p = new PriorityQueue<>(c);//将前 k 个数放入堆中for (int i = 0; i < k; i++) {p.offer(arr[i]);}//将剩下的元素依次和堆顶元素比较//if(元素 >= 堆顶元素):该元素一定不是前 K 个中的元素//else(元素 < 堆顶元素):该元素是候选人,用该元素替换堆顶元素 + 向下调整//若使用 PriorityQueue ,直接删除堆顶元素,再将元素加入优先级队列中即可。for (int i = k; i < arr.length; i++) {int e = arr[i];int t = p.peek();if (e < t) {p.poll();p.offer(e);}}//整个过程完成后,优先级队列中保存的就是我们需要的 Top-K (最小的k个数)//因为题目中,需要返回的是一个数组,所以我们定义一个数组存储 k 个元素。int[] ans = new int[k];for (int i = 0; i < k; i++) {ans[i] = p.poll();}return ans;}public void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}
}

代码二:自己实现优先级队列内部的堆操作(数组)

class Solution {//因为最小的 k 个数,所以需要建大堆public int[] smallestK(int[] arr, int k) {//考虑 k == 0if (k == 0) {return new int[0];}//创建优先级队列 -> 创建一个大堆int[] ans = Arrays.copyOf(arr,k);creatHeap(ans, k);for (int i = k; i < arr.length; i++) {if (arr[i] < ans[0]) {ans[0] = arr[i];adjustDown(ans, k, 0);}}return ans;}//向下调整public static void adjustDown(int[] arr, int size, int index){//1. "我"是否是叶子结点//2. 找到 “我” 的左右孩子中最大的孩子//3. 比较“我”和最大孩子的大小://    我 < 最大的孩子 : 交换//    我 >= 最大的孩子: 不进行交换//4. 交换后更新结点继续向下调整(循环)while (index * 2 + 1 < size){int maxIdx = index * 2 + 1;if (maxIdx + 1 < size && arr[maxIdx] < arr[maxIdx + 1]) {maxIdx = maxIdx + 1;}if (arr[index] >= arr[maxIdx]) {break;}//交换int tmp = arr[index];arr[index] = arr[maxIdx];arr[maxIdx] = tmp;index = maxIdx;}}//建大堆//从最后一个有孩子的双亲结点开始,向下调整,依次到根结点。public static void creatHeap(int[] arr, int size){int pIdx = (size - 2)/2;for (int i = pIdx; i >= 0; i--) {adjustDown(arr,size,i);}}
}

相关文章:

优先级队列(PriorityQueue 和 Top-K问题)

一、PriorityQueue java中提供了两种优先级队列&#xff1a;PriorityQueue 和 PriorityBlockingQueue。其中 PriorityQueue 是线程不安全的&#xff0c;PriorityBolckingQueue 是线程安全的。 PriorityQueue 使用的是堆&#xff0c;且默认情况下是小堆——每次获取到的元素都是…...

计算机组成与设计04——处理器

系列文章目录 本系列博客重点在深圳大学计算机系统&#xff08;3&#xff09;课程的核心内容梳理&#xff0c;参考书目《计算机组成与设计》&#xff08;有问题欢迎在评论区讨论指出&#xff0c;或直接私信联系我&#xff09;。 第一章 计算机组成与设计01——计算机概要与技…...

IT行业那么辛苦,我们为什么还要选择它?

疫情三年&#xff0c;我们学会了什么&#xff1f;工作诚可贵&#xff0c;技能价更高。 搞IT辛苦&#xff1f;有啥辛苦的&#xff1f;说什么辛苦&#xff1f;能有工作&#xff0c;工资又高&#xff0c;还要什么自行车&#xff0c;有啥搞啥吧&#xff01;每次看到网络上有人问有…...

PyTorch学习笔记:nn.CrossEntropyLoss——交叉熵损失

PyTorch学习笔记&#xff1a;nn.CrossEntropyLoss——交叉熵损失 torch.nn.CrossEntropyLoss(weightNone, size_averageNone, ignore_index-100, reduceNone, reductionmean, label_smoothing0.0)功能&#xff1a;创建一个交叉熵损失函数&#xff1a; l(x,y)L{l1,…,lN}T&…...

【VictoriaMetrics】什么是VictoriaMetrics

VictoriaMetrics是一个快速、经济、可扩展的监控解决方案和时间序列数据库,有单机版和集群版本,基础功能及集群版本基本功能不收费,VictoriaMetrics有二进制安装版本、Docker安装版本等多种安装方式,其源码及部署包更新迭代很快,VictoriaMetrics具有以下突出特点: 它可以作…...

(第五章)OpenGL超级宝典学习:统一变量(uniform variable)

统一变量 前言 本篇在讲什么 本篇记录对glsl中的变量uniform的认知和学习 本篇适合什么 适合初学Open的小白 适合想要学习OpenGL中uniform的人 本篇需要什么 对C语法有简单认知 对OpenGL有简单认知 最好是有OpenGL超级宝典蓝宝书 依赖Visual Studio编辑器 本篇的特色 …...

数据存储技术复习(四)未完

1.什么是NAS。一般用途服务器与NAS设备之间有何不同。NAS是一个基于IP的专用高性能文件共享和存储设备。—般用途服务器可用于托管任何应用程序&#xff0c;因为它运行的是一般用途操作系统NAS设备专用于文件服务。它具有专门的操作系统&#xff0c;专用于通过使用行业标准协议…...

Rust编码的信息窃取恶意软件源代码公布,专家警告已被利用

黑客论坛上发布了一个 用Rust编码的信息窃取恶意软件源代码 &#xff0c;安全分析师警告&#xff0c;该恶意软件已被积极用于攻击。 该恶意软件的开发者称&#xff0c;仅用6个小时就开发完成&#xff0c;相当隐蔽&#xff0c; VirusTotal的检测率约为22% 。 恶意软件开发者在…...

diffusers编写自己的推理管道

英文文献&#xff1a;Stable Diffusion with &#x1f9e8; Diffusers 编写自己的推理管道 最后&#xff0c;我们展示了如何使用diffusers. 编写自定义推理管道是对diffusers库的高级使用&#xff0c;可用于切换某些组件&#xff0c;例如上面解释的 VAE 或调度程序。 例如&a…...

计算机操作系统 左万利 第二章课后习题答案

计算机操作系统 左万利 第二章课后习题答案 1、为何引进多道程序设计&#xff0c;在多道程序设计中&#xff0c;内存中作业的道数是否越多越好&#xff1f;说明原因。 引入多道程序设计技术是为了提高计算机系统资源的利用率。在多道程序系统中&#xff0c;内存中作业的道数并…...

CODESYS开发教程10-文件读写(SysFile库)

今天继续我们的小白教程&#xff0c;老鸟就不要在这浪费时间了&#x1f60a;。 前面一期我们介绍了CODESYS的文件操作库CAA File。这一期主要介绍CODESYS的SysFile库所包含的文件读写功能块&#xff0c;主要包括文件路径、名称、大小的获取以及文件的创建、打开、读、写、拷贝…...

Linux安装redis

Linux安装redis一.下载二.解压配置1.创建文件夹2.上传文件3.解压4.编译配置三.启动测试1.启动2.防火墙配置3.测试四.设置开机自启1.配置脚本2.添加服务3.测试一.下载 redis官网&#xff1a;https://redis.io/ redis官方下载地址&#xff1a;http://download.redis.io/releases…...

计算机组成与体系结构 性能设计 William Stallings 第2章 性能问题

2.1 优化性能设计例如&#xff0c;当前需要微处理器强大功能的桌面应用程序包括&#xff1a;图像处理、三维渲染、语音识别、视频会议、多媒体创作、文件的声音和视频注释、仿真建模从计算机组成与体系结构的角度来看&#xff0c;一方面&#xff0c;现代计算机的基本组成与50多…...

anaconda详细介绍、安装及使用(python)

anaconda详细介绍、安装及使用1 介绍1.1 简介1.2 特点1.3 版本下载2 Anaconda管理Python包命令3 安装3.1 windows安装4 操作4.1 Conda 操作4.2 Anaconda Navigator 操作4.3 Spyder 操作4.4 Jupyter Notebook 操作5 示例参考1 介绍 1.1 简介 Anaconda是用于科学计算&#xff08…...

雅思经验(6)

反正我是希望遇到的雅思听力section 4.里面填空的地方多一些&#xff0c;之后单选的部分少一些。练了一下剑9 test3 的section 4&#xff0c;感觉还是不难的&#xff0c;都是在复现&#xff0c;而且绕的弯子也不是很多。本次考试的目标就是先弄一个六分&#xff0c;也就是说&am…...

CentOS9源码编译libvirtd工具

卸载原有版本libvirt [rootcentos9 ~]# yum remove libvirt Centos9配置网络源 [rootcentos9 ~]# dnf config-manager --set-enabled crb [rootcentos9 ~]# dnf install epel-release epel-next-release 安装依赖包 [rootcentos9 ~]# yum install -y libtirpc-devel libxml2-de…...

搭建内网穿透

文章目录摘要npsfrp服务提供商摘要 内网穿透是一种方便的技术&#xff0c;可以让用户随时随地访问内网设备。有两种方式可以使用内网穿透&#xff1a;自己搭建&#xff0c;使用nps/frps软件&#xff1b;购买服务&#xff0c;快速享受内网穿透带来的便利。 nps 内网穿透。参考…...

vue3组件库项目学习笔记(八):Git 使用总结

目前组件库的开发已经接近尾声&#xff0c;因为这次是使用 git 进行协作的开发模式&#xff0c;在团队协作的时候遇到很多的问题&#xff0c;开发过程中发现小伙伴们对于 git 的使用还不是很熟练&#xff0c;这里就简单总结一下常用的 git 的操作&#xff0c;大致有&#xff1a…...

ISO7320FCQDRQ1数字隔离器LMG1025QDEETQ1半桥GaN驱动器

1、数字隔离器 DGTL ISO 3000VRMS 2CH 8SOIC型号&#xff1a;ISO7320FCQDRQ1批次&#xff1a;新技术&#xff1a;容性耦合类型&#xff1a;通用隔离式电源&#xff1a;无通道数&#xff1a;2输入 - 侧 1/侧 2&#xff1a;2/0通道类型&#xff1a;单向电压 - 隔离&#xff1a;30…...

openmmlab 语义分割算法基础

本文是openmmlab AI实战营的第六次课程的笔记&#xff0c;以下是我比较关注的部分。简要介绍语义分割&#xff1a;如下图&#xff0c;左边原图&#xff0c;右边语义分割图&#xff0c;对每个像数进行分类应用语义分割在个各种场景下都非常重要&#xff0c;特别是在自动驾驶和医…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

HTTPS证书一年多少钱?

HTTPS证书作为保障网站数据传输安全的重要工具&#xff0c;成为众多网站运营者的必备选择。然而&#xff0c;面对市场上种类繁多的HTTPS证书&#xff0c;其一年费用究竟是多少&#xff0c;又受哪些因素影响呢&#xff1f; 首先&#xff0c;HTTPS证书通常在PinTrust这样的专业平…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…...

手动给中文分词和 直接用神经网络RNN做有什么区别

手动分词和基于神经网络&#xff08;如 RNN&#xff09;的自动分词在原理、实现方式和效果上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 实现原理对比 对比维度手动分词&#xff08;规则 / 词典驱动&#xff09;神经网络 RNN 分词&#xff08;数据驱动&#xff09…...