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)