LeetCodeDiary

A Diary for solving LeetCode problems

View on GitHub

1723.完成所有工作的最短时间

给你一个整数数组 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 。

提示:

递归 回溯 困难 每日一题

又是不想做题的一天

https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/

题解

class Solution:
    def minimumTimeRequired(self, jobs: List[int], k: int) -> int:

        def check(limit):
            # 小优化,排序后,大的先拿出来试。
            arr = sorted(jobs)

            groups = [0] * k
            # 分成K 组,看看在这个limit 下 能不能安排完工作
            if backtrace(arr, groups, limit):
                return True
            else:
                return False


        def backtrace(arr, groups, limit):
            # 尝试每种可能性
            #print(arr, groups, limit)
            if not arr: return True #分完,则方案可行
            v = arr.pop()

            for i in range(len(groups)):
                if groups[i] + v <= limit:
                    groups[i] += v
                    if backtrace(arr, groups, limit):
                        return True
                    groups[i] -= v

                    # 剪枝,如果这个工人没分到活,那别人肯定得多干活了,那最后的结果必然不是最小的最大值,就不用继续试了。 
                    if groups[i] ==0:
                        break

            arr.append(v)

            return False
        
        #每个人承担的工作的上限,最小为,job 里面的最大值,最大为 jobs 之和
        l, r  = max(jobs), sum(jobs)

        while l < r:
            mid = (l + r)//2

            if check(mid):
                r = mid
            else:
                l = mid + 1

        return l