华为OD机试真题——模拟消息队列(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
2025 A卷 100分 题型
本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!
2025华为OD真题目录+全流程解析/备考攻略/经验分享
华为OD机试真题《模拟消息队列》:
目录
- 题目名称:模拟消息队列
- 题目描述
- Java
- 问题分析
- 解决思路
- Java 代码实现
- 代码解析
- 示例测试
- 示例1:
- 示例2:
- 综合分析
- python
- 问题分析
- 解决思路
- Python 代码实现
- 代码解析
- 示例测试
- 示例1:
- 示例2:
- 综合分析
- JavaScript
- 问题分析
- 解决思路
- JavaScript 代码实现
- 代码解析
- 1. 输入解析
- 2. 事件排序
- 3. 消费者管理
- 4. 消息分发
- 测试用例
- 用例1:
- 用例2:
- 综合分析
- C++
- 问题分析
- 解决思路
- C++ 代码实现
- 代码解析
- 示例测试
- 示例1:
- 示例2:
- 综合分析
- C语言
- 问题分析
- 解决思路
- 完整代码实现
- 代码解析
- 测试用例
- 输入样例1:
- 输出结果:
- 输入样例2:
- 输出结果:
- 综合分析
- GO
- 问题分析
- 解决思路
- 完整代码实现
- 代码解析
- 测试用例
- 输入1
- 输出1
- 输入2
- 输出2
- 综合分析
题目名称:模拟消息队列
属性 | 内容 |
---|---|
知识点 | 事件排序、优先级处理、逻辑处理 |
时间限制 | 1秒 |
空间限制 | 256MB |
限定语言 | 不限 |
题目描述
模拟一个消息队列的运作,包含一个发布者和若干消费者。发布者在特定时刻发送消息,若此时有消费者订阅,消息将发送给优先级最高的消费者(消费者按输入顺序升序排列,升序即优先级递增)。若没有订阅者,消息被丢弃。消费者在特定时刻订阅或取消订阅,同一时刻的事件处理顺序如下:
- 订阅操作优先于消息发送
- 取消订阅优先于消息发送
输入描述
输入为两行:
- 第一行:2N个正整数,表示N条消息的发送时刻和内容(时刻不重复,但未按时间排序)。例如:
2 22 1 11 4 44
代表3条消息,时刻分别为2(内容22)、1(内容11)、4(内容44)。 - 第二行:2M个正整数,表示M个消费者的订阅和取消订阅时刻。例如:
1 7 2 3
代表两个消费者,第一个订阅时刻1、取消时刻7;第二个订阅时刻2、取消时刻3。
输出描述
输出M行,每行为对应消费者收到的消息内容(按接收顺序排列),若未收到消息则输出-1
。
测试用例
-
输入
2 22 1 11 4 44 5 55 3 33 1 7 2 3
输出
11 33 44 55 22
说明:消息在时刻1、2、3、4、5依次处理,优先级高的消费者(后订阅的)优先接收消息。
-
输入
5 64 11 64 9 97 9 11 4 9
输出
97 64
Java
问题分析
我们需要模拟消息队列的工作流程,其中发布者在特定时刻发送消息,消费者在特定时刻订阅或取消订阅。消息发送时,优先发送给当前活跃且优先级最高的消费者。优先级由消费者的输入顺序决定,后订阅的消费者优先级更高。
解决思路
- 事件收集与排序:将所有订阅、取消订阅、消息发送事件按时间排序,同一时刻的事件按订阅 → 取消 → 消息的顺序处理。
- 维护活跃消费者:使用
TreeSet
维护当前活跃的消费者,按优先级(输入顺序的逆序)排序。 - 消息分发:处理消息事件时,将消息发送给当前优先级最高的消费者。
Java 代码实现
import java.util.*;public class Main {static class Event implements Comparable<Event> {int time; // 事件发生时间int type; // 0:订阅, 1:取消订阅, 2:消息int consumerIdx; // 消费者索引(用于订阅/取消)int message; // 消息内容(仅消息事件有效)public Event(int time, int type, int consumerIdx, int message) {this.time = time;this.type = type;this.consumerIdx = consumerIdx;this.message = message;}@Overridepublic int compareTo(Event other) {if (this.time != other.time) {return Integer.compare(this.time, other.time);} else {return Integer.compare(this.type, other.type); // 订阅→取消→消息}}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 解析消息输入String[] msgInput = scanner.nextLine().split(" ");List<Event> events = new ArrayList<>();for (int i = 0; i < msgInput.length; i += 2) {int time = Integer.parseInt(msgInput[i]);int msg = Integer.parseInt(msgInput[i + 1]);events.add(new Event(time, 2, -1, msg)); // 类型2是消息事件}// 解析消费者输入String[] consumerInput = scanner.nextLine().split(" ");int m = consumerInput.length / 2;List<List<Integer>> consumerMsgs = new ArrayList<>();for (int i = 0; i < m; i++) {int subTime = Integer.parseInt(consumerInput[2 * i]);int unsubTime = Integer.parseInt(consumerInput[2 * i + 1]);events.add(new Event(subTime, 0, i, -1)); // 订阅事件events.add(new Event(unsubTime, 1, i, -1)); // 取消事件consumerMsgs.add(new ArrayList<>()); // 初始化消费者的消息列表}// 按时间排序所有事件Collections.sort(events);// 维护当前活跃的消费者(按优先级降序排列)TreeSet<Integer> activeConsumers = new TreeSet<>(Collections.reverseOrder());// 处理所有事件for (Event event : events) {switch (event.type) {case 0: // 订阅事件activeConsumers.add(event.consumerIdx);break;case 1: // 取消订阅事件activeConsumers.remove(event.consumerIdx);break;case 2: // 消息事件if (!activeConsumers.isEmpty()) {int consumer = activeConsumers.first(); // 最高优先级的消费者consumerMsgs.get(consumer).add(event.message);}break;}}// 输出结果for (List<Integer> msgs : consumerMsgs) {if (msgs.isEmpty()) {System.out.println(-1);} else {System.out.println(String.join(" ", msgs.stream().map(String::valueOf).toArray(String[]::new)));}}}
}
代码解析
-
Event 类:
static class Event implements Comparable<Event> {int time; // 事件时间int type; // 0:订阅, 1:取消, 2:消息int consumerIdx; // 消费者索引int message; // 消息内容 }
- 封装事件的时间、类型、消费者索引和消息内容。
-
事件排序:
@Override public int compareTo(Event other) {if (this.time != other.time) return time比较结果;else return type比较结果; // 同一时间,订阅→取消→消息 }
- 按时间升序排序,同一时间的事件按订阅 → 取消 → 消息的顺序处理。
-
解析输入:
String[] msgInput = scanner.nextLine().split(" "); for (int i = 0; i < msgInput.length; i += 2) {int time = Integer.parseInt(msgInput[i]);int msg = Integer.parseInt(msgInput[i + 1]);events.add(new Event(time, 2, -1, msg)); // 消息事件 }
- 将输入拆分为消息时间和内容,生成消息事件。
-
处理消费者事件:
String[] consumerInput = scanner.nextLine().split(" "); for (int i = 0; i < m; i++) {int subTime = Integer.parseInt(consumerInput[2*i]);int unsubTime = Integer.parseInt(consumerInput[2*i+1]);events.add(new Event(subTime, 0, i, -1)); // 订阅事件events.add(new Event(unsubTime, 1, i, -1)); // 取消事件 }
- 解析每个消费者的订阅和取消时间,生成对应事件。
-
维护活跃消费者:
TreeSet<Integer> activeConsumers = new TreeSet<>(Collections.reverseOrder());
- 使用
TreeSet
并按逆序排序,确保活跃消费者中优先级最高的(索引最大)排在前面。
- 使用
-
处理消息事件:
if (!activeConsumers.isEmpty()) {int consumer = activeConsumers.first(); // 最高优先级消费者consumerMsgs.get(consumer)