
华为OD机试 双机位C卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天优快云在线答疑。
一、题目描述
为了提升软件编码能力,小王制定了刷题计划,他选了题库中的 n 道题,编号从 0 到 n-1,并计划在 m 天内按照题目编号顺序刷完所有的题目(注意,小王不能用多天完成同一题)。
在小王刷题计划中,小王需要用 time[i] 的时间完成编号 i 的题目。
此外,小王还可以查看答案,可以省去该题的做题时间。为了真正达到刷题效果,小王每天最多直接看一次答案。
我们定义 m 天中做题时间最多的一天耗时为 T(直接看答案的题目不计入做题总时间)。
请你帮小王求出最小的 T 是多少。
二、输入描述
第一行输入为 time 数组,time[i] 的时间完成编号 i 的题目
第二行输入为 m,m 表示几天内完成所有题目,1 ≤ m ≤ 180
三、输出描述
最小耗时整数 T
四、测试用例
测试用例1:
1、输入
999,999,999
4
2、输出
0
3、说明
在前三天中,小王每天都直接看答案,这样他可以在三天内完成所有的题目并不花任何时间
测试用例2:
1、输入
1,2,2,3,5,4,6,7,8
5
2、输出
4
3、说明
第一天完成前3题,第3题看答案;
第二天完成第4题和第5题,第5题看答案;
第三天完成第6和第7题,第7提看答案;
第四天完成第8题,直接看答案;
第五天完成第9题,直接看答案
五、解题思路
最小化“每天做题时间上限 T”,用二分 + 贪心判定即可。
核心判定:一天内一段连续题目可行当且仅当 sum - max <= T(跳过耗时最大的一题)。
判定方法:对固定 T,用贪心划分每天尽量多的题。一天内可跳过 1 题,故当天有效耗时为 sum - max,只要 sum - max <= T 就可行。
数据结构:数组存储时间;使用累计和与当前最大值即可,空间 O(1)。
六、Java算法源码
public class OdTest {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line1 = br.readLine();
if (line1 == null) return;
String line2 = br.readLine();
if (line2 == null) return;
// 解析 time 数组(逗号分隔,允许空格)
line1 = line1.trim();
if (line1.isEmpty()) return;
String[] parts = line1.split("\\s*,\\s*");
int n = parts.length;
long[] time = new long[n];
long sum = 0;
long maxVal = 0;
for (int i = 0; i < n; i++) {
time[i] = Long.parseLong(parts[i]);
sum += time[i];
if (time[i] > maxVal) maxVal = time[i];
}
int m = Integer.parseInt(line2.trim());
// 二分答案 T,范围 [0, sum]
long left = 0;
long right = sum; // 最大不会超过总和
while (left < right) {
long mid = (left + right) / 2;
if (canFinish(time, m, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
System.out.print(left);
}
// 判定在最大日做题时间 T 下,是否能在 m 天内完成
private static boolean canFinish(long[] time, int m, long T) {
int days = 1;
long sum = 0;
long max = 0;
for (long t : time) {
// 尝试把当前题目加入当天
long newSum = sum + t;
long newMax = Math.max(max, t);
// 若加入后“跳过最大题”的时间仍 <= T,则可继续
if (newSum - newMax <= T) {
sum = newSum;
max = newMax;
} else {
// 开启新的一天
days++;
sum = t;
max = t;
if (days > m) return false;
}
}
return true;
}
}
七、效果展示
1、输入
10,1,1,10
2
2、输出
1
3、说明
分为 [10,1]、[1,10],各自跳过 10,最大 1。

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

7万+

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



