华为OD机试 - LLM推理批次最大化 - 贪心算法(Java 新系统 100分)

本题为经典区间调度问题:给定N个请求区间[Li,Ri],需选择最多互不重叠的区间以最大化推理批次吞吐量。采用贪心算法,按右端点升序排序后遍历,每次选取结束最早且与前一选中区间无重叠(左端点 > lastRight)的区间。时间复杂度O(N log N),空间复杂度O(N),适用于N≤10^5的大规模场景。

在这里插入图片描述

华为OD机试 新系统 题库疯狂收录中,刷题点这里

专栏导读

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

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。

一、题目内容

大语言模型推理时,显存中有一个 KV Cache,用于存储各请求的键值对。现有 N N N 个推理请求排队,第 i i i 个请求需要占用 KV Cache 中一段连续位置 [ L i , R i ] [L_i, R_i] [Li​,Ri​]。每个位置同一时间只能分配给一个请求。请选择尽可能多的请求,使它们的区间互不重叠,从而最大化批次的吞吐量。

补充说明:

  1. [1, 3] 和 [3, 5] 被认为是重叠。

二、输入描述

  • requests:由 N N N 个推理请求构成的二维数组,requests[i] 表示第 i i i 个推理请求,其内容为 [ L i , R i ] [L_i, R_i] [Li​,Ri​]。
  • 数组长度 N N N 满足 1 ≤ N ≤ 10 5 1 \le N \le 10^5 1≤N≤105。
  • 每个位置 [ L i , R i ] [L_i, R_i] [Li​,Ri​] 满足 0 ≤ L i ≤ R i ≤ 10 9 0 \le L_i \le R_i \le 10^9 0≤Li​≤Ri​≤109。

三、输出描述

一个整数,表示最多可选多少个不重叠区间的请求。

四、测试用例

测试用例1:

1、输入

1,3 2,5 4,7 6,9 8,10 11,12

2、输出

4

3、说明

可以选择 [1,3]、[4,7]、[8,10]、[11,12],共 4 个不重叠请求。其他选择无法获得更多请求。

测试用例2:

1、输入

1,3 2,4 3,3 4,4

2、输出

2

3、说明

可以选择 [3,3] 和 [4,4]。虽然 [1,3] 与 [3,3] 只在位置 3 相交,但仍属于重叠,因此不能同时选择。

五、解题思路

解题思路

1. 问题分析

本题是经典的区间调度问题。给定 N 个闭区间,需要选择尽可能多的区间,使任意两个选中区间都不重叠。由于区间包含左右端点,因此两个区间只有在前一个区间的右端点严格小于后一个区间的左端点时,才能同时被选中。

2. 数据结构选择

使用 ArrayList<long[]> 存储请求区间,每个long 数组包含左端点和右端点。该结构存储简单,支持遍历与排序。考虑到 N 最大为 10^5,使用数组列表能够满足存储要求。

3. 算法设计

采用贪心算法,首先按照区间右端点升序排序。当右端点相同时,按照左端点升序排序。

排序完成后,从左到右依次检查每个区间。使用 lastRight 保存最后一个已选区间的右端点,初始值设置为 -1。

如果当前区间的左端点大于 lastRight,说明两者不存在重叠,可以选择当前区间,将答案加一,并更新 lastRight。

否则跳过当前区间,继续检查后面的区间。

4. 贪心策略的正确性

选择结束最早的区间,可以为后续区间保留尽可能大的可用位置范围。假设某个最优方案首先选择了一个结束更晚的区间,可以将其替换成当前结束最早的可选区间,而不会影响后续区间的选择。

因此,每次选择结束最早的可用区间不会降低最优解,最终能够得到最多的不重叠请求数量。

5. 复杂度分析

时间复杂度:O(N log N),主要来自区间排序。

排序后的贪心遍历为 O(N)。

空间复杂度:O(N),用于保存所有请求区间。

额外的贪心状态仅需要 O(1) 空间。

该算法可以高效处理 N <= 10^5 的数据规模。

六、Java算法源码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OdTest {

    public static void main(String[] args) {

        List<long[]> requests = new ArrayList<>();

        // 1. 使用 Scanner 读取一整行输入
        // 用户按下回车后,立即开始处理,不需要等待 EOF
        try (Scanner scanner = new Scanner(System.in)) {

            if (!scanner.hasNextLine()) {
                System.out.println(0);
                return;
            }

            String input = scanner.nextLine();

            // 2. 使用正则表达式提取所有非负整数
            // 支持逗号、空格、换行以外的其他分隔符
            // 例如:1,3 2,5 4,7
            // 也支持:[[1,3],[2,5],[4,7]]
            Matcher matcher = Pattern.compile("\\d+").matcher(input);

            List<Long> numbers = new ArrayList<>();

            while (matcher.find()) {
                numbers.add(Long.parseLong(matcher.group()));
            }

            // 3. 每两个数字组成一个区间 [L, R]
            for (int i = 0; i + 1 < numbers.size(); i += 2) {
                long left = numbers.get(i);
                long right = numbers.get(i + 1);

                requests.add(new long[]{left, right});
            }
        }

        // 4. 按照区间右端点升序排序
        // 右端点相同时,按照左端点升序排序
        requests.sort((a, b) -> {
            int result = Long.compare(a[1], b[1]);

            return result != 0
                    ? result
                    : Long.compare(a[0], b[0]);
        });

        // 5. 贪心算法选择不重叠区间
        long lastRight = -1;
        int answer = 0;

        for (long[] interval : requests) {

            // 闭区间端点相等也算重叠,因此必须严格大于
            if (interval[0] > lastRight) {

                answer++;

                // 更新最后一个已选区间的右端点
                lastRight = interval[1];
            }
        }

        // 6. 输出最终结果
        System.out.println(answer);
    }
}

七、效果展示

1、输入

0,0 0,0 0,1 1,1 2,2 2,3 3,3

2、输出

4

3、说明

可以选择 [0,0]、[1,1]、[2,2]、[3,3],共 4 个请求。重复的 [0,0] 只能选择一个,而 [2,3] 不能与 [2,2] 或 [3,3] 同时选择。

在这里插入图片描述


🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 新系统 200分)

🏆本专栏收录于《华为OD机试(JAVA)真题》。

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值