[LintCode] 438. Copy Books II
Given n
books and each book has the same number of pages. There are k
persons to copy these books and the i-th
person needs times[i]
minutes to copy a book.
Each person can copy any number of books and they start copying at the same time. What's the best strategy to assign books so that the job can be finished at the earliest time?
Return the shortest time.
Example 1:
Input: n = 4, times = [3, 2, 4]
Output: 4
Explanation:
First person spends 3 minutes to copy 1 book.
Second person spends 4 minutes to copy 2 books.
Third person spends 4 minutes to copy 1 book.
Example 2:
Input: n = 4, times = [3, 2, 4, 5]
Output: 4
Explanation: Use the same strategy as example 1 and the forth person does nothing.
给定 n
本书, 每本书具有相同的页数. 现在有 k
个人来复印这些书. 其中第 i
个人需要 times[i]
分钟来复印一本书. 每个人可以复印任意数量的书. 怎样分配这 k
个人的任务, 使得这 n
本书能够被尽快复印完?
返回完成复印任务最少需要的分钟数。
题目给了几个变量,其中 n 代表有 n 本书需要复印。这里我们有 K 个人参与复印,每个人的复印速度都存在 time是数组里,我们要求的是最快复印完所有的书的时间。
这道题也是属于在答案上二分的题目。对于这道题,最快可以在 0 分钟内复印完(压根没有书可以复印),最慢只安排一个人参与复印(注意例子2,题目是允许有人不参与复印的)。那么我们二分的上界和下界就由此得出了。其中,只有一个人参与复印的时候,他所花的时间是 times[0] * n。这里 times[0] 是任意取的,意思是随便只挑一个人复印,但是实际情况肯定是多人参与复印。我们对这个范围进行二分,每得到一个 mid 的时候,我们根据这个 mid 的时间去统计如果所有人都参与复印,是否有可能把所有的书都复印完。如果能复印完,说明这个 mid 还可以更小,end--;如果无法复印完,则 start++,说明需要更多时间。
时间O(nlogn)
空间O(1)
Java实现
1 public class Solution { 2 public int copyBooksII(int n, int[] times) { 3 int left = 0; 4 int right = n * times[0]; 5 while (left + 1 < right) { 6 int mid = left + (right - left) / 2; 7 if (check(times, n, mid)) { 8 right = mid; 9 } else { 10 left = mid; 11 } 12 } 13 if (check(times, n, left)) { 14 return left; 15 } 16 return right; 17 } 18 19 // 返回是否能够在mid的时间内复印完成n本书 20 static boolean check(int[] times, int n, int mid) { 21 int sum = 0; 22 int len = times.length; 23 for (int i = 0; i < len; i++) { 24 sum += mid / times[i]; 25 } 26 return sum >= n; 27 } 28 }