这道题是经典的工作分配问题,目标是将 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 上是标准答案,能高效通过所有测试用例。

 

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐