
华为OD机试 新系统 题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
在数据包传输系统中,为了优化网络带宽利用率,系统需要对数据包序列进行处理,找出每个数据包右侧第一个满足某些条件、优先级更高的数据包。
每个数据包的格式为:<priority>:<weight>,其中:
<priority>是数据包的优先级(正整数,1 ≤ priority ≤ 10^5,数值越大优先级越高)<weight>是数据包的权重(正整数,1 ≤ weight ≤ 10^5)
系统需要按照以下规则处理数据包:搜索整个数据包序列(从左到右),对于每个数据包,找出其右侧第一个同时满足如下条件的数据包:
- 条件1:目标数据包的
priority必须大于当前数据包的priority - 条件2:目标数据包的
weight必须等于当前数据包的weight
请编写一个方法,实现数据包右侧第一个满足条件的数据包查找功能。
二、输入描述
参数 packets:数据包内容,长度为 n(正整数,1 ≤ n ≤ 10^5)的数组,每个元素为 [priority, weight]。
三、输出描述
右侧第一个满足条件的数据包 ID 组成的数组序列;数据包 ID 是其在数组中的位置,即第 i i i 个数据包的 ID 为(从 1 开始计数,非数组下标 0);如果某个数据包右侧没有满足条件的数据包,则输出 0。
四、测试用例
测试用例1:
1、输入
5,10 6,10 4,10
2、输出
2,0,0
3、说明
数据包:
ID1 = 5,10
ID2 = 6,10
ID3 = 4,10
对于 ID1:
ID2 weight = 10
ID2 priority = 6 > 5
所以答案是 ID2。
ID2 和 ID3 后面都没有符合要求的数据包。
输出:2,0,0
测试用例2:
1、输入
5,10 7,22
2、输出
0,0
3、说明
虽然:7 > 5
但是:10 != 22
weight 不相等,所以 ID1 不能选择 ID2。
输出:0,0
五、解题思路
使用 HashMap + 单调栈:Map<weight, Stack<index>>
不同 weight 的数据包互不影响,因此每个 weight 单独维护一个单调栈。
从左向右扫描数据包。假设当前数据包为:
priority = currentPriority
weight = currentWeight
只查看 currentWeight 对应的栈。如果:栈顶数据包 priority < currentPriority
说明当前数据包满足栈顶数据包的两个要求:weight 相同,并且 priority 更大。
而且,因为是从左往右扫描,所以当前数据包一定是栈顶数据包右侧第一个符合条件的数据包。
不断弹出所有 priority 小于当前 priority 的栈顶元素,并把它们的答案设置成当前数据包 ID。
六、Java算法源码
public class OdTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<int[]> packets = new ArrayList<>();
String[] arr = scanner.nextLine().split(" ");
for (int i = 0; i < arr.length; i++) {
String[] split = arr[i].split(",");
packets.add(new int[]{Integer.valueOf(split[0]), Integer.valueOf(split[1])});
}
scanner.close();
int[] result = findNextPackets(packets);
// 按照题目要求输出:2,0,0
StringJoiner joiner = new StringJoiner(",");
for (int id : result) {
joiner.add(String.valueOf(id));
}
System.out.println(joiner);
}
/**
* 查找每个数据包右侧第一个:
* 1. weight 相同
* 2. priority 更大
* 的数据包 ID。
*/
private static int[] findNextPackets(List<int[]> packets) {
int n = packets.size();
/*
* Java 的 int 数组默认初始化为 0。
* 因此最终仍没有找到符合条件的数据包时,
* 不需要额外处理,答案天然就是 0。
*/
int[] result = new int[n];
/*
* key :weight
* value :当前 weight 下尚未找到答案的数据包下标栈
*
* 每个 weight 都拥有自己独立的单调栈。
* 栈中的 priority 从栈底到栈顶保持单调不增。
*/
Map<Integer, Deque<Integer>> stacksByWeight = new HashMap<>();
for (int i = 0; i < n; i++) {
int currentPriority = packets.get(i)[0];
int currentWeight = packets.get(i)[1];
/*
* 取得当前 weight 对应的栈。
* 如果之前没有出现过这种 weight,
* 则新建一个空栈。
*/
Deque<Integer> stack =
stacksByWeight.computeIfAbsent(
currentWeight,
k -> new ArrayDeque<>()
);
/*
* 栈里的数据包和当前数据包 weight 一定相同。
*
* 如果当前 priority 大于栈顶 priority,
* 那么当前数据包就是栈顶数据包右侧
* 第一个满足条件的数据包。
*
* 为什么可以确定是“第一个”?
* 因为我们是严格按照从左到右的顺序扫描,
* 如果之前已经出现过符合条件的数据包,
* 栈顶元素早就会被弹出,不可能保留到现在。
*/
while (!stack.isEmpty()
&& packets.get(stack.peek())[0] < currentPriority) {
int previousIndex = stack.pop();
/*
* 数组下标从 0 开始,
* 题目中的数据包 ID 从 1 开始,
* 所以当前数据包 ID = i + 1。
*/
result[previousIndex] = i + 1;
}
/*
* 当前数据包暂时还不知道答案,
* 放入对应 weight 的单调栈中,
* 等待后面出现优先级更大的数据包。
*/
stack.push(i);
}
return result;
}
}
七、效果展示
1、输入
3,5 5,5 4,5 6,5
2、输出
2,4,4,0
3、说明
对应:
ID1: 3,5
ID2: 5,5
ID3: 4,5
ID4: 6,5
因此:
ID1 -> ID2
ID2 -> ID4
ID3 -> ID4
ID4 -> 0
输出:2,4,4,0

🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 新系统 200分)
🏆本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

5242

被折叠的 条评论
为什么被折叠?



