题目描述
给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。
请你将这些工作分配给 k 位工人。所有工作都应该分配给工人,且每项工作只能分配给一位工人。工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。
返回分配方案中尽可能 最小 的 最大工作时间 。
-
示例 1:
输入:jobs = [3,2,3], k = 3
输出:3
解释:给每位工人分配一项工作,最大工作时间是 3 。 -
示例 2:
输入:jobs = [1,2,4,7,8], k = 2
输出:11
解释:按下述方式分配工作:
1 号工人:1、2、8(工作时间 = 1 + 2 + 8 = 11)
2 号工人:4、7(工作时间 = 4 + 7 = 11)
最大工作时间是 11 。
提示:
1 <= k <= jobs.length <= 12
1 <= jobs[i] <= 107
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
此题难以直接找出正确答案(当然可以用dp),不过可以发现,若数值n可以作为“工人的最大工作时间”,那么比n大的数就完全可以不用考虑了。因此可以用二分查找法找出正确答案(找的过程是不断试错的过程)。下限是工作时长最长的值,上限是所有工作时长的和。
那么如何确定n是否可以作为“工人的最大工作时间”呢?我们采取回溯+剪枝的策略。开辟一个长度为k的数组,表示每个工人的总工作时长。
工作的分配顺序是从用时多往用时少,每份工作均先从0号员工开始尝试分配,若满足“工人的最大工作时间”要求则尝试给当前员工分配工作,并继续递归下去,若后续递归中无法满足要求则需回溯,若回溯至递归开头仍然无法寻找到满足要求的方案,说明当前“工人的最大工作时间”过短,二分法的左节点便更新为当前“工人的最大工作时间”+1。若成功找到分配方案,说明当前“工人的最大工作时间”是可行的,答案一定小于等于此时间,二分法的右节点便更新为当前“工人的最大工作时间”,继续二分查找下去。
代码详解
class Solution {
public int minimumTimeRequired(int[] jobs, int k) {
Arrays.sort(jobs); // 先排序
int len = jobs