千问 1723.完成所有工作的最短时间 public int minimumTimeRequired(int[] jobs, int k)
这道题是经典的工作分配问题,目标是将 jobs 数组中的工作分配给 k 个工人,使得完成所有工作的最短时间(即所有工人中最大工作时间)最小。3. 剪枝2(空工人优化):如果一个任务无法放入一个空闲工人(时间为0),那它也无法放入其他空闲工人,直接 break。// 剪枝2:如果当前工人时间为0,分配失败,说明这个任务无法放入任何空工人,直接返回。2. 剪枝1(去重):如果两个工人当前时间相同,分配
这道题是经典的工作分配问题,目标是将 jobs 数组中的工作分配给 k 个工人,使得完成所有工作的最短时间(即所有工人中最大工作时间)最小。
🧠 问题分析
- 每个工作必须分配给一个工人。
- 每个工人可以处理多个工作。
- 总时间是所有工人中工作时间最长的那个。
- 目标:最小化这个最大值。
这是一个典型的最小化最大值问题,适合用 二分答案 + 回溯(DFS) 或 动态规划 + 状态压缩 来解决。但由于 jobs.length 0 && workers[i] == workers[i-1]) {
continue;
}
if (workers[i] + job <= limit) {
workers[i] += job;
if (dfs(jobs, index + 1, workers, limit)) {
return true;
}
workers[i] -= job;
}
// 剪枝2:如果当前工人时间为0,分配失败,说明这个任务无法放入任何空工人,直接返回
if (workers[i] == 0) {
break;
}
}
return false;
}
private void reverse(int[] arr) {
int i = 0, j = arr.length - 1;
while (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
}
🔍 关键点说明
1. 排序 + 逆序:将任务从大到小排序,优先分配大任务,能更快触发剪枝。
2. 剪枝1(去重):如果两个工人当前时间相同,分配给第二个和第一个效果一样,跳过。
3. 剪枝2(空工人优化):如果一个任务无法放入一个空闲工人(时间为0),那它也无法放入其他空闲工人,直接 break。
4. 二分边界:
- left = max(jobs):至少需要一个工人做最大任务。
- right = sum(jobs):最坏情况一个工人做所有任务。
📈 复杂度分析
- 时间复杂度:O(log(sum - max) × k^n),其中 n 是任务数。但由于剪枝,实际运行很快。
- 空间复杂度:O(k + n),递归栈和工人数组。
✅ 示例
jobs = [3,2,3], k = 3
→ 每人做一个,最大时间为 3
→ 返回 3
jobs = [1,2,4,7,8], k = 2
→ 最优分配:[1,2,4] 和 [7,8] → 最大时间为 15
→ 但更优:[1,2,7] 和 [4,8] → 最大时间为 12
→ 实际最优是 11?需验证
→ 算法会找到最小可能的最大值
这个解法在 LeetCode 上是标准答案,能高效通过所有测试用例。
更多推荐




所有评论(0)