完成所有工作的最短时间 II
难度:
标签:
题目描述
代码结果
运行时间: 150 ms, 内存: 30.6 MB
/*
* Leetcode 2323: 完成所有工作的最短时间 II
* 题目思路:
* 使用Java Stream API优化代码,先排序,然后二分查找最小的最大工作时间,再用回溯法验证。
*/
import java.util.Arrays;
public class Solution {
public int minimumTimeRequired(int[] jobs, int k) {
Arrays.sort(jobs);
int left = jobs[jobs.length - 1];
int right = Arrays.stream(jobs).sum();
while (left < right) {
int mid = (left + right) / 2;
if (canFinish(jobs, k, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
private boolean canFinish(int[] jobs, int k, int limit) {
int[] workers = new int[k];
return backtrack(jobs, workers, jobs.length - 1, limit);
}
private boolean backtrack(int[] jobs, int[] workers, int idx, int limit) {
if (idx < 0) return true;
int curJob = jobs[idx];
for (int i = 0; i < workers.length; i++) {
if (workers[i] + curJob <= limit) {
workers[i] += curJob;
if (backtrack(jobs, workers, idx - 1, limit)) return true;
workers[i] -= curJob;
}
if (workers[i] == 0) break;
}
return false;
}
}
解释
方法:
此题解的核心思想是将每个工作分配给一个工人,使得完成所有工作所需的总时间最短。首先,将工作和工人的列表分别进行排序。排序后,最大的工作可以被最高效的工人来完成,次大的工作被次高效的工人完成,以此类推。这种方法可以确保工作与工人的效率相匹配,从而最小化完成所有工作的最大时间。对于每对工作和工人,计算完成该工作所需的时间,即 `(a + b - 1) // b`,其中 `a` 是工作量,`b` 是工人的效率。这个计算确保了整数除法的正确上取整。最后,返回这些时间中的最大值,这就是完成所有工作所需的最短时间。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在解决这个问题时选择将工作和工人列表都进行排序?这样排序的主要目的是什么?
▷🦆
在配对工作和工人时,`zip(jobs, workers)`的使用是否意味着工作和工人的数量必须完全相同?如果不相同会怎样处理?
▷🦆
如果工作和工人的效率分布极为不均匀,这种配对方式是否还是有效的?有没有可能通过调整配对策略进一步优化结果?
▷