1723. 完成所有工作的最短时间
作者:互联网
题目来源:1723. 完成所有工作的最短时间
// 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。
// 请你将这些工作分配给 k 位工人。所有工作都应该分配给工人,且每项工作只能分配给一位工人。
// 工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。
// 返回分配方案中尽可能 最小 的 最大工作时间 。
方法一:二分查找 + 回溯 + 剪枝
个人思路:说实话初始看到这个题没有啥思路,于是直接看题解。看完题解恍然大悟,从中学到了几点:
1. 明确要达成的目标,“分配方案中尽可能 最小 的 最大工作时间”。可以理解为尽可能的平均分配工作,不出现忙的忙,闲的闲的情况,然后看这个最优方案中最长的工时。
2. 目标明确后,再看要求‘每项工作只能分配给一位工人’,这里我们得出 这个时间必然大于完成单项工作最大花费时间,即jobs中最大值。
3. 极限的分配方案是所有工作都由一个人来完成,即完成所有工作花费时间, jobs的和值。
4. 这样就确认了一个区间[max(jobs), sum(jobs)],如果有check函数能确认某个值limit,满足将jobs分配给k个工人且每个工人的工时不大于limit,
则我们可以用二分查找来确定最终的值。
5. 此时复杂的问题被我们拆分为两部分:
一、区间【max(jobs), sum(jobs)】用二分查找确认最终的值。
二、check函数能确认某个值limit,满足将jobs分配给k个工人且每个工人的工时不大于limit。
6. check函数中几个优化措施(直接搬运题解)
优先分配工作量大的工作。感性地理解,如果要求将小石子和大石块放入玻璃瓶中,优先放入大石块更容易使得工作变得简单。
在搜索过程中,优先分配工作量小的工作会使得工作量大的工作更有可能最后无法被分配。
/** * @param {number[]} jobs * @param {number} k * @return {number} */ var minimumTimeRequired = function(jobs, k) { jobs.sort((a,b)=>b-a); let n = jobs.length; let l = jobs[0]; let r = 0; for(let i = 0;i<n;i++){ r+=jobs[i]; } while(l<r){ let mid = Math.floor((l+r)/2); if(check(jobs,k,mid)){ r=mid; }else{ l=mid+1; } } return l; }; function check(jobs,k,limit) { let works = new Array(k).fill(0); let n = jobs.length; const f = (w,i)=>{ if(i>=n){ return true; } let cur = jobs[i]; for(let j=0;j<k;j++){ if(w[j]+cur<=limit){ w[j]+=cur; if(f(w,i+1)) return true; w[j]-=cur; } if(w[j] === 0 || w[j]+cur === limit){ break; } } return false; } return f(works,0) }
标签:jobs,1723,工作,let,完成,工人,短时间,limit,分配 来源: https://blog.51cto.com/u_15201483/2776350