打印机队列

题目描述

有5台打印机打印文件,每台打印机有自己的待打印队列。
因为打印的文件内容有轻重缓急之分,所以队列中的文件有1~10不同的代先级,其中
数字越大优先级越高
打印机会从自己的待打印队列中选择优先级最高的文件来打印。
如果存在两个优先级一样的文件,则选择最早进入队列的那个文件。
现在请你来模拟这5台打印机的打印过程。

输入描述

每个输入包含1个测试用例,

每个测试用例第一行给出发生事件的数量N(0 < N < 1000)。

接下来有 N 行,分别表示发生的事件。共有如下两种事件:

  1. “IN P NUM”,表示有一个拥有优先级 NUM 的文件放到了打印机 P 的待打印队列中。(0< P <= 5, 0 < NUM <= 10);
  2. “OUT P”,表示打印机 P 进行了一次文件打印,同时该文件从待打印队列中取出。(0 < P <= 5)。

输出描述

  • 对于每个测试用例,每次”OUT P”事件,请在一行中输出文件的编号
  • 如果此时没有文件可以打印,请输出”NULL“。
  • 文件的编号定义为”IN P NUM”事件发生第 x 次,此处待打印文件的编号为x。编号从1开始。

用例

输入 7
IN 1 1
IN 1 2
IN 1 3
IN 2 1
OUT 1
OUT 2
OUT 2
输出 3
4
NULL
说明
输入 5
IN 1 1
IN 1 3
IN 1 1
IN 1 3
OUT 1
输出 2
说明

源码和解析
解析:

1.可以使用有序列表对该题进行求解,但是这种每次添加任务队列都需要解决排序的问题,可以考虑在打印任务时再看是否有序,若无序,则可以排队,若有序,则直接输出首个任务,且直接移出这个任务。
2.另外一种方式就是使用大根堆去解决这个问题

示例代码方式一:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;public class T35 {static class Task {int num;int priority;int taskId;public Task(int num, int priority, boolean isFinished,int taskId) {super();this.num = num;this.priority = priority;this.taskId = taskId;}@Overridepublic String toString() {return "Task [num=" + num + ", priority=" + priority+ ", taskId=" + taskId + "]\n";}}// 按输入的设备编号进行分堆 存放在不同的map中 键是打印机编号 值为该打印机的任务信息static Map<Integer, List<Task>> taskMap = new HashMap<Integer, List<Task>>();static List<Integer> pList = new ArrayList<>();// 记录设备的id集// 后面就不用keyset去遍历map了static boolean isOrdered = false;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();int id = 0;for (int i = 0; i < num; i++) {id++;String op = scanner.next();int p = scanner.nextInt();int priority = 0;if (op.equals("IN")) {priority = scanner.nextInt();}if (!taskMap.containsKey(p)) {List<Task> tasks = new ArrayList<T35.Task>();taskMap.put(p, tasks);pList.add(p);}Task task = new Task(p, priority, false, id);if (op.equals("IN")) {taskMap.get(p).add(task);isOrdered = false;} else {if (!isOrdered)sort();List<Task> tasksItem = taskMap.get(p);Task t = tasksItem.size() == 0 ? null : tasksItem.get(0);if (t != null) {tasksItem.remove(0);}System.out.println((t == null ? "NULL" : t.taskId));}}}// 排序public static void sort() {isOrdered = true;for (int p : pList) {taskMap.get(p).sort(new Comparator<Task>() {@Overridepublic int compare(Task o1, Task o2) {// 优先级降序 高的排前面 方便取值if (o1.priority > o2.priority) {return -1;} else if (o1.priority < o2.priority) {return 1;}// 优先级一样 任务顺序排序if (o1.taskId < o2.taskId) {return -1;} else if (o1.taskId > o2.taskId) {return 1;}return 0;}});}}
}

执行示意图如下:


大根堆解法
解析

例如输入
10
IN 1 2
IN 1 1
IN 1 4
IN 1 2
IN 1 4
IN 1 3
IN 1 5
OUT 1
OUT 2
OUT 2
形成的节点信息如下

那么在移出时就
OUT 1 针对 1 5 这个节点
OUT 1 查找到 1 5这个节点 无比他大 比他小的 那么只能是1 5 节点的父节点 1 4
OUT 1 查找到 1 4 节点是已完成的 那么可能就是1 3 节点 若1 3节点已完成 则可能是1 2 节点 若 1 2 节点已完成 则可能是其左节点1 1 若 1 1节点已完成 则看其左节点 若 1 1 节点未完成 则看其左节点
注意:这里并非是完全排序好的大根堆,而是依据节点的添加顺序形成的堆

源码示例 大根堆

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class T35 {static class Task {int devId; // 设备编号int priority;int taskId;boolean isFinished;Task leftTask; // 左节点Task rightTask; // 右节点Task parenTask;// 父节点@Overridepublic String toString() {return "Task [devId=" + devId + ", priority=" + priority+ ", taskId=" + taskId + "]\n";}}// 按输入的设备编号进行分堆 存放在不同的map中 键是打印机编号 值为该打印机的任务信息static Map<Integer, Task> taskMap = new HashMap<Integer, Task>();static Task objTask = null;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();int id = 0;for (int i = 0; i < num; i++) {id++;String op = scanner.next();int devId = scanner.nextInt();int priority = 0;if (op.equals("IN")) {priority = scanner.nextInt();}Task task = new Task();task.devId = devId;task.priority = priority;task.taskId = id;if (op.equals("IN")) {if (!taskMap.containsKey(devId)) {taskMap.put(devId, task);System.out.println("挂载跟节点:" + task.taskId);} else {// 挂载节点handle(devId, task);}} else {// 出节点objTask = null;find(taskMap.get(devId));if (objTask == null)System.out.println("NULL");}}}// 找到目标设备要出的那个public static void find(Task task) {if (task.isFinished == false) {// 自己未完成 那么可能到右侧if (task.rightTask != null && task.rightTask.isFinished == false) {find(task.rightTask);// 找右侧子节点 这种是不可能找左侧子节点的} else {// 到自己task.isFinished = true;objTask = task;System.out.println(task.taskId);// 输出任务id}} else {// 当前已完成 那么只有可能是其左侧节点if (task.leftTask != null)find(task.leftTask);}}public static void handle(int devId, Task task) {Task rootTask = taskMap.get(devId);mount(rootTask, task);}// 遍历节点 进行挂载public static void mount(Task task, Task objTask) {if (task.priority < objTask.priority) {// 挂载右侧if (task.rightTask != null) {mount(task.rightTask, objTask);} else {task.rightTask = objTask;System.out.println("节点" + objTask.taskId + "挂载在节点"+ task.taskId + "右侧");}} else {// 挂载左侧if (task.leftTask != null) {mount(task.leftTask, objTask);} else {task.leftTask = objTask;System.out.println("节点" + objTask.taskId + "挂载节点" + task.taskId+ "左侧");}}}
}

大根堆代码运行示意图:

华为OD机试之打印机队列(Java源码)相关推荐

  1. 【满分】【华为OD机试真题2023 JAVA】 打印文件

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 打印文件 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 有5台打印机打印文件,每台打印机有自己的待打印队列.因为打印的 ...

  2. 【华为OD机试真题2023 JAVA】不含101的数

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 不含101的数 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 小明在学习二进制时,发现了一类不含101的数,也就是: ...

  3. 【华为OD机试真题2023 JAVA】硬件产品销售方案

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 硬件产品销售方案 知识点递归数组DFS搜索回溯 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 某公司目前推出了AI开发 ...

  4. 【华为OD机试真题2023 JAVA】网上商城优惠活动(一)

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 网上商城优惠活动(一) 时间限制:1s 空间限制:50MB 限定语言:不限 题目描述: [背景] 某网上商城举办优惠活动,发布了满减.打折 ...

  5. 【华为OD机试真题2023 JAVA】字母组合

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 字母组合 知识点回溯 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 每个数字对应多个字母,对应关系如下: 0:a,b, ...

  6. 【华为OD机试真题2023 JAVA】几何平均值最大子数组

    华为OD机试真题,2023年度机试题库全覆盖,刷题指南点这里 几何平均值最大子数组 知识点数组二分查找 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 从一个长度为N的正数数组num ...

  7. 华为OD机试 - 预订酒店(Java JS Python)

    题目描述 放暑假了,小明决定到某旅游景点游玩,他在网上搜索到了各种价位的酒店(长度为n的数组A),他的心理价位是x元,请帮他筛选出k个最接近x元的酒店(n>=k>0),并由低到高打印酒店的 ...

  8. 华为OD机试 - 完美走位(Java JS Python)

    题目描述 在第一人称射击游戏中,玩家通过键盘的A.S.D.W四个按键控制游戏人物分别向左.向后.向右.向前进行移动,从而完成走位. 假设玩家每按动一次键盘,游戏任务会向某个方向移动一步,如果玩家在操作 ...

  9. 华为OD机试 - 德州扑克(Java JS Python)

    题目描述 五张牌,每张牌由牌大小和花色组成,牌大小2~10.J.Q.K.A,牌花色为红桃.黑桃.梅花.方块四种花色之一. 判断牌型: 牌型1,同花顺:同一花色的顺子,如红桃2红桃3红桃4红桃5红桃6. ...

最新文章

  1. 请求分页系统中页面分配策略与页面置换策略的关系
  2. 下拉列表select显示ng-options
  3. error C2504: “XXXXXXX”: 未定义基类
  4. 前端学习(1799):前端调试之清除浮动
  5. android绘制论文,基于Android平台的三维地形绘制研究与实现
  6. ICCV 2019 Oral 端到端任意形状场景文字识别
  7. SharePlex数据库复制解决方案
  8. R语言统计—配对t检验样本量计算
  9. 用计算机制作演示文稿教案博客,《制作多媒体演示文稿》教学案例
  10. 对接萤石平台调用播放
  11. OneNote中英文格式不同,OneNote无法修改英文字体,OneNote默认英文字体为Calibri无法修改的问题。
  12. 6翻了 (15 分)
  13. 知識は潜在能力、行動は力CommentsAdd Star
  14. mac苹果系统安装虚拟机方法教程 虚拟机操作之一
  15. pythonturtle八卦_太极八卦连环掌——python大法好
  16. JVM/JDK/JRE/IDE—区别
  17. 官网实例详解4.37(pretrained_word_embeddings.py)-keras学习笔记四
  18. 微信小程序 ECharts 水球图
  19. 数据挖掘的R包和函数的集合
  20. Java项目:SSM图书馆图书管理借阅书籍管理系统

热门文章

  1. revit学习-图元属性
  2. Python 常用编程方法
  3. LTE测量文件MRO,MRE.MRS的区别解释
  4. 第七届“飞思卡尔”杯全国大学生智能汽车竞赛 赛后感想
  5. 杭州记忆 | 科达为G20做的三件事
  6. linux云计算主要就业岗位有哪些
  7. CreateJs的拖拽、碰撞检测函数封装
  8. 课堂/会议同屏教学解决方案之RTSP/RTP over UDP组播解决方案
  9. layui框架的使用
  10. 搭建网站选择租用哪里的服务器