华为OD机试真题 新系统 Java实现 【数据包优先级窗口查找】
数据包优先级窗口查找
华为OD新系统机试真题 华为OD新系统上机考试真题 5月13号 100分题型
更多语言题解可点击查看:华为OD机试新系统真题 - 数据包优先级窗口查找(C/C++/Py/Java/Js/Go)题解
华为OD机试新系统真题目录点击查看: 华为OD机试真题题库目录|机考题库 + 算法考点详解
题目内容
给定 n n n 个数据包,每个数据包包含 i d id id 和 p r i o r i t y priority priority。维护一个大小为 k k k 的滑动窗口,对于每个窗口,找出窗口内每个数据包右边第一个 p r i o r i t y priority priority 更高的数据包 i d id id。
输入描述
- n n n: 数据包数量 ( 1 ≤ n ≤ 10 6 1 ≤ n ≤ 10^6 1≤n≤106)
- k k k: 窗口大小 ( 1 ≤ k ≤ 100 1 ≤ k ≤ 100 1≤k≤100)
- p a c k e t s packets packets: 数据包内容,长度为 n n n 的数组,每个元素格式为 i d : p r i o r i t y id:priority id:priority
数据包格式: - 格式: < i d > : < p r i o r i t y > <id>:<priority> <id>:<priority>
- i d id id: 唯一标识符 ( 1 ≤ i d ≤ 10 9 1 ≤ id ≤ 10^9 1≤id≤109)
- p r i o r i t y priority priority: 优先级 ( 1 ≤ p r i o r i t y ≤ 10 9 1 ≤ priority ≤ 10^9 1≤priority≤109),数值越大优先级越高
处理规则: - 窗口滑动: 从左到右滑动,每次窗口包含 k k k 个连续数据包
- 每个窗口的处理:
- 向右查找第一个 p r i o r i t y priority priority 更高的数据包
- 找到 → 记录该数据包的 i d id id
- 未找到 → 不记录
- 跳过条件: 数据包不足以构成完整窗口 (窗口大小 k > k > k> 数据包总数 n n n) → → → 跳过该窗口 窗口内未找到任何 p r i o r i t y priority priority 更高的数据包 → → → 跳过该窗口
输出描述
输出所有未跳过窗口的结果序列,每个序列包含该窗口内找到的所有"下一个更高优先级数据包 i d id id"
样例1
输入
5
3
1:5 2:3 3:7 4:6 5:4
输出
3,3 3
说明
窗口 [ 0 , 2 ] [0,2] [0,2]: 数据包为 [ 1 : 5 , 2 : 3 , 3 : 7 ] [1:5, 2:3, 3:7] [1:5,2:3,3:7]
1 : 5 1:5 1:5 后面第一个优先级更高的是 3 : 7 3:7 3:7,输出 3 3 3
2 : 3 2:3 2:3 后面第一个优先级更高的是 3 : 7 3:7 3:7,输出 3 3 3
3 : 7 3:7 3:7 后面没有优先级更高的,不输出
该窗口输出: 3 3 3 3 3 3
窗口 [ 1 , 3 ] [1,3] [1,3]: 数据包为 [ 2 : 3 , 3 : 7 , 4 : 6 ] [2:3, 3:7, 4:6] [2:3,3:7,4:6]
2 : 3 2:3 2:3 后面第一个优先级更高的是 3 : 7 3:7 3:7,输出 3 3 3
3 : 7 3:7 3:7 后面没有优先级更高的,不输出
4 : 6 4:6 4:6 后面没有优先级更高的,不输出
该窗口输出: 3 3 3
窗口 [ 2 , 4 ] [2,4] [2,4]: 数据包为 [ 3 : 7 , 4 : 6 , 5 : 4 ] [3:7, 4:6, 5:4] [3:7,4:6,5:4]
3 : 7 3:7 3:7 后面没有优先级更高的,不输出
4 : 6 4:6 4:6 后面没有优先级更高的,不输出
5 : 4 5:4 5:4 后面没有优先级更高的,不输出
该窗口无输出
样例2
输入
4
3
1:1 2:2 3:3 4:4
输出
2,3 3,4
说明
窗口 [ 0 , 2 ] [0,2] [0,2]: 数据包为 [ 1 : 1 , 2 : 2 , 3 : 3 ] [1:1, 2:2, 3:3] [1:1,2:2,3:3]
1 : 1 1:1 1:1 后面第一个优先级更高的是 2 : 2 2:2 2:2,输出 2 2 2
2 : 2 2:2 2:2 后面第一个优先级更高的是 3 : 3 3:3 3:3,输出 3 3 3
3 : 3 3:3 3:3 后面没有优先级更高的,不输出
输出: 2 2 2 3 3 3
窗口 [ 1 , 3 ] [1,3] [1,3]: 数据包为 [ 2 : 2 , 3 : 3 , 4 : 4 ] [2:2, 3:3, 4:4] [2:2,3:3,4:4]
2 : 2 2:2 2:2 后面第一个优先级更高的是 3 : 3 3:3 3:3,输出 3 3 3
3 : 3 3:3 3:3 后面第一个优先级更高的是 4 : 4 4:4 4:4,输出 4 4 4
4 : 4 4:4 4:4 后面没有优先级更高的,不输出
输出: 3 3 3 4 4 4
样例3
输入
4
3
4:4 3:3 2:2 1:1
输出
说明
窗口 [ 0 , 2 ] [0,2] [0,2]: 数据包为 [ 4 : 4 , 3 : 3 , 2 : 2 ] [4:4, 3:3, 2:2] [4:4,3:3,2:2]
4 : 4 4:4 4:4 后面没有优先级更高的,不输出
3 : 3 3:3 3:3 后面没有优先级更高的,不输出
2 : 2 2:2 2:2 后面没有优先级更高的,不输出
该窗口不输出
窗口 [ 1 , 3 ] [1,3] [1,3]: 数据包为 [ 3 : 3 , 2 : 2 , 1 : 1 ] [3:3, 2:2, 1:1] [3:3,2:2,1:1]
3 : 3 3:3 3:3 后面没有优先级更高的,不输出
2 : 2 2:2 2:2 后面没有优先级更高的,不输出
1 : 1 1:1 1:1 后面没有优先级更高的,不输出
该窗口不输出
所有窗口均无输出
样例4
输入
3
4
1:5 2:3 3:7
输出
说明
窗口大小 4 > 4> 4> 数据包数量 3 3 3,窗口无输出,无满足结果输出
题解
思路
思路:单调栈
-
预处理:使用
单调栈算法计算每个数据包右边第一个priority更高的数据包下标。具体逻辑为:- 定义
stk维持一个单调递减栈,栈中存储数据包下标。定义nextMaxIndex数组,存储每个位置右边第一个priority更高的数据包下标,开始所有值初始化为-1. - 遍历输入数据包,遍历i时的处理逻辑:
- 递归维持栈递减,当栈非空,并且栈顶元素
j小于当前数据优先级时,说明该位置为j右侧第一个大于它的下标,更新nextMaxIndex[j] = i,并弹出栈顶元素。 - 将
i压入栈中,等待被处理。
- 递归维持栈递减,当栈非空,并且栈顶元素
- 定义
-
注意
n < k时,直接返回为空即可。 -
由于k <=100,可以枚举所有窗口,并求出每个窗口的结果序列,以这个
{i, i + k -1}为例:- 使用
currentWindRes存储当前窗口结果。 - 确定窗口边界为
windClose = i + k - 1 - 从前往后遍历
{i, i + k -1}, 当前位置为j,如果nextMaxIndex[j] == -1或者nextMaxIndex[j] > windClose直接跳过(当前窗口内没有优先级更高)。否则加入{packets[j].id, packets[nextMaxIndex[j]].id} - 按照3的逻辑处理之后,如果
currentWindRes为空说明改窗口无输出,不添加进最终结果。
- 使用
code
import java.util.*;
public class Main {
public static List<List<Integer>> priorityPackets(int n, int k, List<int[]> packets) {
List<List<Integer>> res = new ArrayList<>();
if (n < k) return res;
int[] nextMaxIndex = new int[n];
Arrays.fill(nextMaxIndex, -1);
Stack<Integer> stack = new Stack<>();
// 单调栈:找下一个更大值
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() &&
packets.get(i)[1] > packets.get(stack.peek())[1]) {
nextMaxIndex[stack.pop()] = i;
}
stack.push(i);
}
// 枚举窗口
for (int i = 0; i <= n - k; i++) {
int r = i + k - 1;
List<Integer> cur = new ArrayList<>();
for (int j = i; j <= r; j++) {
if (nextMaxIndex[j] != -1 && nextMaxIndex[j] <= r) {
cur.add(packets.get(nextMaxIndex[j])[0]);
}
}
if (!cur.isEmpty()) {
res.add(cur);
}
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine().trim());
int k = Integer.parseInt(sc.nextLine().trim());
String[] arr = sc.nextLine().trim().split(" ");
List<int[]> packets = new ArrayList<>();
for (String s : arr) {
String[] tmp = s.split(":");
packets.add(new int[]{
Integer.parseInt(tmp[0]),
Integer.parseInt(tmp[1])
});
}
List<List<Integer>> res = priorityPackets(n, k, packets);
if (res.isEmpty()) return;
for (int i = 0; i < res.size(); i++) {
if (i > 0) System.out.print(" ");
for (int j = 0; j < res.get(i).size(); j++) {
if (j > 0) System.out.print(",");
System.out.print(res.get(i).get(j));
}
}
}
}
更多推荐

所有评论(0)