华为OD机试之打印机队列(Java源码)

打印机队列

题目描述

有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;
		}

		@Override
		public 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>() {
				@Override
				public 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;// 父节点

		@Override
		public 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
						+ "左侧");
			}
		}
	}
}

大根堆代码运行示意图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/24020.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows 上安装和启动 Nacos 2.2.2 最新版本

文章目录 前言版本声明本地启动1. 下载 Nacos2. 开启鉴权配置3. 持久化数据库4. 启动 Nacos5. 启动测试 联系我 前言 本文旨在为您详细介绍如何安装和启动 Nacos 2.2.2 的最新版本&#xff0c;以及为 youlai-mall 开源商城版本的升级做好准备工作。 版本声明 名称版本操作系…

3年外包裸辞,面试阿里、字节全都一面挂,哭死.....

测试员可以先在外包积累经验&#xff0c;以后去大厂就很容易&#xff0c;基本不会被卡&#xff0c;事实果真如此吗&#xff1f;但是在我身上却是给了我很大一巴掌... 所谓今年今天履历只是不卡简历而已&#xff0c;如果面试答得稀烂&#xff0c;人家根本不会要你。况且要不是大…

c#快速入门

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析2 目录 &#x1f449;&#x1f3fb; c#和c不同之处&#x1f449;&#x1f3fb;程序文件的…

已签名驱动程序安装后提示“Windows无法验证此设备所需驱动程序数字签名”的原因和解决方法

在Windows 64位系统上&#xff0c;正常开启数字签名认证时&#xff0c;驱动程序软件需要经过微软数字签名的才允许被使用。否则在设备管理器下&#xff0c;安装完硬件驱动后设备上会有“黄色感叹号”标识&#xff0c;右键该设备属性提示&#xff1a;“Windows 无法验证此设备所…

SY8205同步降压DCDC可调电源模块(原理图和PCB)

SY8205同步buck降压电源模块&#xff0c;输入电压4.5-30V&#xff0c;输出电压0.6-30V可调&#xff0c;效率90%以上&#xff0c;最大连续输出电流5A&#xff0c;峰值电流6A。 开源链接&#xff1a;https://url.zeruns.tech/obGu3 SY8025数据手册下载地址&#xff1a;https://…

公文写作素材:为人处世类过渡句50例

1.身处逆境&#xff0c;敢于亮剑&#xff0c;坚毅前行&#xff0c;方能逆势突围&#xff1b;面对困难&#xff0c;坚定信心&#xff0c;敢拼敢闯&#xff0c;定能笑到最后。 2.没有海纳百川的胸怀&#xff0c;怎能容得下不同性格的人&#xff1b;没有从善如流的雅量&#xff0…

java程序1补充:从键盘输入圆的半径,求圆的周长和面积(简易与交互两版)

编写一个java程序&#xff0c;从键盘输入圆的半径&#xff0c;求圆的周长和面积&#xff0c;并输出。 要求&#xff1a; &#xff08;1&#xff09;半径仅考虑int型正整数&#xff0c;并综合利用所学较好地处理异常输入&#xff0c;包括非法整数、负整数输入时的处理。输入半…

大模型对世界的改变,从一时一地,到无处不在、无时不有

作者 | 曾响铃 文 | 响铃说 大模型正在中国遍地开花&#xff0c;做过的没做过的都要过来参合一下。 汹涌浪潮中&#xff0c;不免有更多人开始关注那个最先发布的文心一言。 全球科技大厂中第一个发布GPT大模型产品的百度&#xff0c;在刚刚的中关村论坛上透露了一些文心一言…

OpenCV中的图像处理3.7-3.8(五)边缘检测、图像金字塔

目录 3.7 边缘检测目标理论OpenCV中的Canny边缘检测其他资源练习 3.8 图像金字塔目标理论使用金字塔进行图像混合其他资源 翻译及二次校对&#xff1a;cvtutorials.com 编辑者&#xff1a;廿瓶鲸&#xff08;和鲸社区Siby团队成员&#xff09; 3.7 边缘检测 目标 在本章中&a…

ChatGPT在智能外呼机器人领域的应用

随着人工智能技术的不断发展&#xff0c;自然语言处理(NLP)技术也逐渐成为各行各业的热门技术。其中&#xff0c;ChatGPT技术是近年来备受关注的技术之一。ChatGPT技术是一种基于自然语言处理和深度学习的人工智能技术&#xff0c;它可以处理自然语言文本&#xff0c;实现自动化…

智能排班系统 【管理系统功能、操作说明——上篇】

文章目录 功能设计共有功能系统管理员企业管理员门店管理员门店员工 页面与功能展示用户登录企业注册系统首页系统管理员首页企业管理员首页门店管理员首页 个人中心菜单管理日志管理操作日志登录日志 功能设计 不同的角色关注的任务和功能不同&#xff0c;针对不同的角色&…

Docker安装OpenWrt

我笔记本MacOs安装Docker OpenWrt 失败了,网络一直容器内外无法访问. 今天使用虚拟机安装一下,虚拟机使用Parallels,系统使用kali 一、安装docker sudo apt install docker.io 二、把网卡混杂模式打开 根据您当前的ip查看网卡&#xff01;&#xff01;&#xff01; 在您的liu…

【Python json】零基础也能轻松掌握的学习路线与参考资料

Python中的JSON模块主要用于将Python对象序列化成JSON数据或解析包含JSON数据的字符串。JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。由于JSON在Web应用中的广泛使用…

pdf怎么压缩得小一点?软件压缩更高效

PDF可以在不同操作系统和设备上实现高保真的排版和格式化。然而&#xff0c;随着文档的不断增多和文件大小的增加&#xff0c;传输和存储PDF文件也变得越来越困难。为了解决这个问题&#xff0c;可以使用PDF压缩技术来减小文件大小&#xff0c;提高传输效率。本文将介绍PDF压缩…

自动驾驶汽车的安全技术特点

“安全第一”是自动驾驶的核心理念和价值观。 自动驾驶车辆的整体系统安全设计是一项复杂的系统工程&#xff0c; 涉及车载自动驾驶系统的核心算法策略设计、 硬件和软件冗余安全设计、远程云代驾技术、 全流程测试验证技术等&#xff0c; 并遵循功能安全&#xff08;ISO 2626…

git代码回滚是使用reset还是revert

时光不能回退&#xff0c;Git却允许我们改变历史。 想要让Git回退历史&#xff0c;有以下步骤&#xff1a; 使用git log命令&#xff0c;查看分支提交历史&#xff0c;确认需要回退的版本 使用git reset --hard commit_id命令&#xff0c;进行版本回退 使用git push origin命…

华为OD机试之完美走位(Java源码)

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

2023年上半年系统集成项目管理工程师上午真题及答案解析

1.在( )领域我国远末达到世界先进水平&#xff0c;需要发挥新型国家体制优势&#xff0c;集中政府和市场两方面的力量全力发展。 A.卫星导航 B.航天 C.集成电路 D.高铁 2.ChatGPT 于2022年11月30日发布&#xff0c;他是人工智能驱动( )。 …

计算机组成原理-中央处理器-控制器功能和原理

目录 一、硬布线控制器 二、硬布线控制器的设计(硬件) 2.1分析每个阶段的微操作序列(取址、间址、执行、中断) 2.2选择cpu的控制方式 2.3 安排微操作时序 2.4电路设计 2.4.1列出操作时间表 2.4.2 写出微操作命令的最简表达式 2.4.3画出电路图 *三、微程序控制器基本原理 四…

日撸 Java 三百行day56-57

文章目录 day56-57 kMeans 聚类1.kMeans聚类理解2.代码理解2.1代码中变量的理解2.2代码理解 day56-57 kMeans 聚类 1.kMeans聚类理解 无监督的机器学习算法&#xff0c;其中k是划分为几个簇&#xff0c;并且选择k个数据作为不同簇的聚类中心&#xff0c;计算每个数据样本和聚…