【华为OD题库-038】支持优先级的对列-java
题目
实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。
如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。
队列存储的数据内容是一个 整数。
输入描述
一组待存入队列的数据(包含内容和优先级)。
输出描述
队列的数据内容(优先级信息输出时不再体现)。
补充说明
不用考虑数据不合法的情况,测试数据不超过100个。
示例1
输入:
(10,1),(20,1).(30,2).(40,3)
输出:
40,30,10,20
说明:
输入样例中,向队列写入了4个数据,每个数据由数据内容和优先级组成。输入和输出内容都不含空格。数据40的优先级最高,所以最先输出,其次是30;10和20优先级相同,所以按输入顺序输出
示例2
输入:
(10,1),(10,1).(30,2).(40,3)
输出:
40,30,10
说明:
输入样例中,向队列写入了4个数据,每个数据由数据内容和优先级组成输入和输出内容都不含空格。
数据40的优先级最高,所以最先输出,其次是30;两个10和10构成重复数据,被丢弃一个。
思路
基础的数据结构题,大概三个思路:
- 直接放入list,转对象排序,可以实现要求
- 使用内置的PriorityQueue对象实现
- 自定义数据结构实现
猜测考察点在第三点,不然前两个虽然能达到目的,但是没有意义
排序实现
分析题目,排序规则为:
- 优先级高的先出,
- 同优先级时位置靠前的先出;
- 数据和优先级均相同的去重
基于以上分析,可以采用以下步骤实现:
- 新建一个data对象,含有priority,val,idx三个属性,idx代表出现位置
- 把输入转为data对象放入list中
- 先去重(利用HashSet),根据priority,val判重,重写equals方法
- 自定义排序规则,priority降序,idx升序排列。Data实现Comparable接口,重写compareTo方法
PriorityQueue实现
还是一样,新建Data对象,重写equals(去重用)和compareTo(排序用)方法
把输入转为Data对象后,直接加入PriorityQueue中
重复对象都加入到了PriorityQueue,在输出时,因为结果已经按照自定义排序规则写好了,所以去重逻辑就是当前项等于上一项时,代表重复,此时不输出对应结果即可
自定义数据结构实现
可以用两个栈实现优先级队列
stackA:优先级高的在栈顶,存放较小优先级
stackB:优先级低的在栈顶,存放较大优先级,也就是说在stackB中的优先级始终比stackA的优先级大,比如某个状态如下:
最后再输出结果时,只需要把stackB依次出栈再入stackA栈,再输出stackA的栈顶元素即可得到:6,5,4,3,2,1。即按优先级降序排列。
具体存放数据逻辑如下,以20 10 30 40 50为例:
存入20,首先判断它是较大优先级还是较小优先级?我们可以和stackB的栈顶元素比较(当然和stackA的栈顶元素比较也可以)。如果cur<stackB.peek()。说明是一个比stackB最低优先级还要小的元素,所以它是一个较小优先级,应该存入stackA中。此处stackB为空,没有栈顶元素,我们也先出入stackA中,由于stackA没有数据,直接存入,如下:
存入10,stackB为空,所以还是存入stackA中,但是此时stackA有数据,由于定义的stackA要将较大优先级放入栈顶,即当前元素如果比stackA的栈顶元素还要小(cur<stackA.peek())时,应该把大于当前优先级的数据转入stackB
存入30,大于stackB的栈顶元素,此时应该存入stackB,同样的逻辑,这里stackB是将优先级小的放入栈顶,所以cur>stackB.peek()时,应该把小于当前优先级的数据转入stackA
存入40,大于stackB栈顶元素,存入stackB,将stackB小于当前优先级的元素放入stackA中
存入50,大于stackB栈顶元素,存入stackB,将stackB小于当前优先级的元素放入stackA中
最后输出结果,需要将stackB中的全部数据转入stackA,再依次从stackA栈顶取数据得到:50 40 30 20 10
上面的过程没有考虑优先级相同和去重时的处理逻辑,现在分析如下:
优先级相同,比如在上面的数据中再加入一个30,30小于stackB的栈顶元素,所以应该放入stackA中,将stackA大于30的元素全部弹出来:
关键在于等于30是否弹出?如果弹出,那么我们将第二个30加入到了stackA的栈顶,第一个30弹入了stackB的栈顶,最后输出结果时,一定是先输出的第一个30。符合题意,否则的话,会先输出第二个30。所以在stackA入栈时,判断条件是:cur<=stackA.peek()
假设最后加入的不是30而是50,此时弹出到stackA时,不应该取等,即cur>stackB.peek(),即只弹出比stackB栈顶元素还大的值
如上,因为栈顶和50相等,不弹出stackA,直接加入,最后的结果一定是第一个50先输出来。去重,根据第一点,优先级相同时的处理逻辑可以发现,当优先级相同时,始终会把之前的数据放入到stackB中去,所以我们再向stackA或者stackB加入数据时,只要判断其不等于stackB的栈顶元素即可(相等判断逻辑为优先级和值同时相同,重写equals方法实现)
题解
三种方法都定义了实体Data:
class Data implements Comparable<Data> {private int priority;private int val;private int idx;public Data(int priority, int val, int idx) {this.priority = priority;this.val = val;this.idx = idx;}public int getIdx() {return idx;}public void setIdx(int idx) {this.idx = idx;}public int getPriority() {return priority;}public void setPriority(int priority) {this.priority = priority;}public int getVal() {return val;}public void setVal(int val) {this.val = val;}public Data(int priority, int val) {this.priority = priority;this.val = val;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Data data = (Data) o;return priority == data.priority &&val == data.val;}@Overridepublic int hashCode() {return Objects.hash(priority, val);}@Overridepublic int compareTo(Data o) {if (this.priority != o.priority) return o.priority - this.priority;return this.idx - o.idx;}
}
排序实现
package hwod;import java.util.*;
import java.util.stream.Collectors;public class MyPriorityQueue {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String inputs = sc.nextLine();System.out.println(myPriorityQueue(inputs));}/*** 直接排序输出** @param str* @return*/private static String myPriorityQueue(String str) {//将输入解析为自定义对象DataSet<Data> set = new HashSet<>();String[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");for (int i = 0; i < arrs.length; i++) {String[] cur = arrs[i].split(",");set.add(new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]), i));}List<Data> list = set.stream().sorted().collect(Collectors.toList());StringBuilder sb = new StringBuilder();for (int i = 0; i < list.size(); i++) {if (i != 0) sb.append(",");sb.append(list.get(i).getVal());}return sb.toString();}
}
PriorityQueue实现
package hwod;import java.util.*;
import java.util.stream.Collectors;public class MyPriorityQueue {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String inputs = sc.nextLine();System.out.println(myPriorityQueue(inputs));}/*** 使用java自带的优先级队列** @param str* @return*/private static String myPriorityQueue(String str) {//将输入解析为自定义对象DataString[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");PriorityQueue<Data> queue = new PriorityQueue<>();for (int i = 0; i < arrs.length; i++) {String[] cur = arrs[i].split(",");Data data = new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]),i);queue.add(data);}StringBuilder sb = new StringBuilder();Data lst = null;int size = queue.size();while (!queue.isEmpty()) {Data data = queue.poll();if (!data.equals(lst)) {lst = data;if (size != queue.size()+1) sb.append(",");sb.append(data.getVal());}}return sb.toString();}
}
自定义数据结构实现
package hwod;import java.util.*;
import java.util.stream.Collectors;public class MyPriorityQueue {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String inputs = sc.nextLine();System.out.println(myPriorityQueue(inputs));}/*** 用两个栈实现优先级对列** @param str* @return*/private static String myPriorityQueue2(String str) {//将输入解析为自定义对象DataString[] arrs = str.substring(1, str.length() - 1).split("\\),\\(");Myqueue queue = new Myqueue();for (int i = 0; i < arrs.length; i++) {String[] cur = arrs[i].split(",");Data data = new Data(Integer.parseInt(cur[1]), Integer.parseInt(cur[0]));queue.add(data);}StringBuilder sb = new StringBuilder();int size = queue.getSize();while (!queue.isEmpty()) {if (queue.getSize() != size) sb.append(",");sb.append(queue.remove().getVal());}return sb.toString();}
}
class Myqueue {private LinkedList<Data> stackA = new LinkedList<>();//存小数,大堆顶private LinkedList<Data> stackB = new LinkedList<>(); //存大数,小堆顶public void add(Data data) {if (stackB.isEmpty() || data.getPriority() <= stackB.peekLast().getPriority()) {//比stackB栈顶元素还小,说明是一个较低优先级,应该存在stackA中//和stackB栈顶元素相等,说明有两个优先级相等的data,比如(30,1),(10,1),题目要求按照输入顺序输出,那么可以等价于后出现的优先级相对更低// 即此处的优先级等于和小于等价while (!stackA.isEmpty() && data.getPriority() <= stackA.peekLast().getPriority()) {stackB.addLast(stackA.removeLast());}//优先级相等时,始终会把之前的数据放入stackB中去if (!stackB.isEmpty() && stackB.peekLast().equals(data)) return;stackA.addLast(data);} else {while (!stackB.isEmpty() && data.getPriority() > stackB.peekLast().getPriority()) {stackA.addLast(stackB.removeLast());}if (!stackB.isEmpty() && stackB.peekLast().equals(data)) return;stackB.addLast(data);}}public Data remove() {while (!stackB.isEmpty()) {stackA.addLast(stackB.removeLast());}return stackA.removeLast();}public int getSize() {return stackA.size() + stackB.size();}public boolean isEmpty() {return getSize() == 0;}
}
推荐
如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。
相关文章:

【华为OD题库-038】支持优先级的对列-java
题目 实现一个支持优先级的队列,高优先级先出队列,同优先级时先进先出。 如果两个输入数据和优先级都相同,则后一个数据不入队列被丢弃。 队列存储的数据内容是一个 整数。 输入描述 一组待存入队列的数据(包含内容和优先级)。 输出描述 队列…...

python爱心代码高级
在Python中,我们可以使用matplotlib库来创建一个更高级的爱心图形。以下是一个示例: import matplotlib.pyplot as pltimport numpy as npx np.linspace(-2, 2, 1000)y1 np.sqrt(1-(abs(x)-1)**2)y2 -3*np.sqrt(1-(abs(x)/2)**0.5)fig, ax plt.subp…...

基于SSM+Vue的社区共享食堂管理系统
基于SSM的社区共享食堂管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringMyBatisSpringMVC工具:IDEA/Ecilpse、Navicat、Maven 系统展示 主页 菜品详情 管理员界面 摘要 社区共享食堂管理系统是一种基于SSM…...
MYSQL基础知识之【修改数据,删除数据】
文章目录 前言MySQL UPDATE 查询使用PHP脚本更新数据 MySQL DELETE 语句从命令行中删除数据使用 PHP 脚本删除数据 后言 前言 hello world欢迎来到前端的新世界 😜当前文章系列专栏:Mysql 🐱👓博主在前端领域还有很多知识和技术…...
【机器学习】交叉验证 Cross-validation
交叉验证(CrossValidation)方法思想简介 以下简称交叉验证(Cross Validation)为CV.CV是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train set),另一部分做为验证集(validation set),首先用训练集对分类器进…...

Pycharm修改文件默认打开方式 + CSV Editor插件使用
1、File —> Settings —> Editor —> File Types 然后将*csv添加到最上面 在plugins中下载插件,CSV Editor 备注:不在上一步的“File Types”中将*.csv设置为CSV格式,插件是不起作用的 就可以使用了...

shiro整合redis
shiro整合redis 前言:shiro默认的session是存储在jvm内存中的,这样会导致java服务内存占用更大以及一旦服务器宕机或者版本迭代需要重启服务时,缓存中的数据不能恢复,导致用户需要重新登录认证,体验很差。因此利用第三…...
HarmonyOS(七)——@BuilderParam装饰器
前言: 前面我们认识了Builder装饰器:自定义构建函数,今天我们继续认识下一个装饰器——BuilderParam装饰器。 当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接…...

展开运算符(...)
假如我们有一个数组: const arr [7,8,9];● 我们如果想要数组中的元素,我们必须一个一个手动的去获取,如下: const arr [7,8,9]; const badNewArr [5, 6, arr[0], arr[1],arr[2]]; console.log(badNewArr);● 但是通过展开运…...

Apache Flink(二):数据架构演变
🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹…...

【C++】类与对象(中)
一、类的默认成员函数 如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会自…...

webshell之无扩展免杀
1.php加密 这里是利用phpjiami网站进行加密,进而达到加密效果 加密前: 查杀效果 可以看到这里D某和某狗都查杀 里用php加密后效果 查杀效果 可以看到这里只有D某会显示加密脚本,而某狗直接绕过 2.dezend加密 可以看到dezend加密的特征还是…...

用 VirtualBox 安装 OpenWrt 等 Linux 系统,无法启动的解决办法
用 VirtualBox 安装 OpenWrt 等 Linux 系统,无法启动的解决办法 最近新买了台联想小新 Pro 14 2023 锐龙版,因为有 32GB 的运行内存,所以想安装虚拟机以充分发挥。一开始使用 Hyper-V 来安装可以正常使用,但是后面想使用 Virtual…...

Windows下搭建Tomcat HTTP服务,发布公网远程访问
文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 前言 Tomcat作为一个轻量级的服务器,不仅名字很有趣࿰…...

k8s-daemonset、job、cronjob控制器 6
Daemonset控制器(一个节点部署一个) 、 创建Daemonset控制器 控制节点上不能进行部署,有污点 解决方式: 扩容节点,token值过期的解决方法: 回收pod job控制器 需要使用perl镜像,仓库没有&…...

技术面时,一定要掌握这3个关键点
前言 现在有这么多优秀的测试工程师,大家都知道技术面试是不可避免的一个环节,一般技术面试官都会通过自己的方式去考察你的技术功底与基础理论知识。 如果你参加过一些大厂面试,肯定会遇到一些这样的问题: 1、看你项目都用到了…...

[Linux]进程创建➕进程终止
文章目录 1.再谈fork()函数1.1fork()创建子进程 OS都做了哪些工作?1.2对上述问题的理解1.3写时拷贝进行父子进程分离的优势1.4了解eip寄存器和pc1.5了解进程的上下文数据1.6对计算机组成的理解1.7fork常规用法1.8fork调用失败的原因 2.进程终止2.1进程终止时操作系统要做的工作…...
【隐私计算】算术秘密分享的加法和乘法运算(Beaver Triple预处理)
在安全多方计算中(MPC)中,算术秘密分享是最基础的机制。一直有在接触,但是一直没有整理清楚最基础的加法和乘法计算流程。 算术秘密分享 概念: 一个位宽为 l l l-bit的数 x x x,被拆分为两个在 Z 2 l \ma…...

【LeetCode刷题-字符串】--71.简化路径
71.简化路径 思路: 对于给定的字符串,先根据/分割成一个由若干字符串组成的列表,记为names,根据题意names中包含的字符串只能是以下几种: 空字符串一个点两个点只包含英文字母、数字或_的目录名 对于空字符串和一个…...

数据结构与算法(Java)-树形DP题单
树形DP(灵神笔记) 543 二叉树的直径 543. 二叉树的直径 - 力扣(LeetCode) 给你一棵二叉树的根节点,返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...