华为OD机试真题 Java 实现【模拟消息队列】【2023 B卷 100分】,附详细解题思路

在这里插入图片描述

目录

    • 专栏导读
    • 一、题目描述
    • 二、输入描述
    • 三、输出描述
    • 四、解题思路
    • 五、Java算法源码
    • 六、效果展示
      • 1、输入
      • 2、输出
      • 3、说明

华为OD机试 2023B卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

一、题目描述

让我们来模拟一个消息队列的运作,有一个发布者和若干个消费者,发布者会在给定的时刻向消息队列发送消息。

  • 若此时消息队列有消费者订阅,这个消息会被发送到订阅的消费者中优先级最高(输入中消费者按优先级升序排列)的一个;
  • 若此时没有订阅的消费者,该消息被消息队列丢弃。

消费者则会在给定的时刻订阅消息队列或取消订阅。

  • 当消息发送和订阅发生在同一时刻时,先处理订阅操作,即同一时刻订阅的消费者成为消息发送的候选。
  • 当消息发送和取消订阅发生在同一时刻时,先处理取消订阅操作,即消息不会被发送到同一时刻取消订阅的消费者。

二、输入描述

输入为两行。

第一行为2N 个正整数,代表发布者发送的N个消息的时刻和内容(为方便解折,消息内容也用正整教表示)。第一个数字是第一个消息的发送时刻,第二个数字是第一个消息的内容,以此类推。用例保证发送时刻不会重复,但注意消息并没有按照发送时刻排列。

第二行为2M个正整数,代表M个消费者订阅和取消订阅的时刻。第一个数字是第一个消费者订阅的时刻,第二个数字是第一个消费者取消订阅的时刻,以此类堆。用例保证每个消费者的取消订阅时刻大于订阅时刻,消费者按优先级 升席排列。

两行的数字都由空格分隔。N不超过100,M不超过10,每行的长度不超过1000字符。

三、输出描述

输出为M行,依次为M个消费者收到的消息内容,消息内容按收到的顺序排列,且由空格分隔;
若某个消费者没有收到任何消息,则对应的行输出−1。

四、解题思路

  1. 输入发布者发送的N个消息的时刻和内容;
  2. 输入M个消费者订阅和取消订阅的时刻;
  3. 定义二维数组,发布者publisherArrs[时刻][内容];
  4. 按时刻排序;
  5. 定义二维数组,消费者consumerArrs[订阅][取消];
  6. 建立消费关系列表relationList;
  7. 遍历发布者publisherArrs,根据订阅和取消订阅关系将消息发送给消费者;
    • 判断消息是否被消费者订阅,跳出循环;
  8. 输出为M行,依次为M个消费者收到的消息内容;

五、Java算法源码

package com.guor.od;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class OdTest {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 发布者发送的N个消息的时刻和内容
        int[] publisherArr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        // M个消费者订阅和取消订阅的时刻
        int[] consumerArr = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        // 发布者二维数组[时刻][内容]
        int[][] publisherArrs = new int[publisherArr.length / 2][];
        for (int i = 0, j = 0; i < publisherArr.length; i += 2) {
            publisherArrs[j++] = new int[]{publisherArr[i], publisherArr[i + 1]};
        }
        // 按时刻排序
        Arrays.sort(publisherArrs, (a, b) -> a[0] - b[0]);

        // 消费者二维数组[订阅][取消]
        int[][] consumerArrs = new int[consumerArr.length / 2][];
        for (int i = 0, j = 0; i < consumerArr.length; i += 2) {
            consumerArrs[j++] = new int[]{consumerArr[i], consumerArr[i + 1]};
        }

        // 消费关系列表
        ArrayList<ArrayList<Integer>> relationList = new ArrayList<>();
        for (int j = 0; j < consumerArrs.length; j++) {
            relationList.add(new ArrayList<>());
        }

        // 遍历发布者,根据订阅和取消订阅关系将消息发送给消费者
        for (int i = 0; i < publisherArrs.length; i++) {
            for (int j = consumerArrs.length - 1; j >= 0; j--) {
                // 判断消息是否被消费者订阅
                if (publisherArrs[i][0] >= consumerArrs[j][0] && publisherArrs[i][0] < consumerArrs[j][1]) {
                    relationList.get(j).add(publisherArrs[i][1]);
                    break;
                }
            }
        }

        // 输出为M行,依次为M个消费者收到的消息内容
        for (int i = 0; i < relationList.size(); i++) {
            if (relationList.get(i).isEmpty()) {
                System.out.println("-1");
            } else {
                String result = "";
                for (Integer x : relationList.get(i)) {
                    result += x + " ";
                }
                System.out.println(result.trim());
            }
        }
    }
}

六、效果展示

1、输入

2 200 1 100 4 400 5 500 3 300
1 7 2 3

2、输出

100 300 400 500
200

3、说明

消息100在1时刻到达,此时只有第一个消费者订阅,消息发送给它;

消息200在2时刻到达,此时两个消费者都订阅了,消息发送给优先级最高的第二个消费者;

消息300在时刻3到达,此时只有第一个消费者订阅,消息发送给它,

余下的消息按规则也是发送给第一个消费者。

华为OD机试真题 Java 实现【模拟消息队列】【2023 B卷 100分】,附详细解题思路_第1张图片


下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法

本文收录于,华为OD机试(JAVA)真题(A卷+B卷)

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

你可能感兴趣的:(搬砖工逆袭Java架构师,java,学习,docker,云原生)