Description
Given n
books and the i-th
book has pages[i]
pages. There are k
persons to copy these books.
These books list in a row and each person can claim a continous range of books. For example, one copier can copy the books from i-th
to j-th
continously, but he can not copy the 1st book, 2nd book and 4th book (without 3rd book).
They start copying books at the same time and they all cost 1 minute to copy 1 page of a book. What's the best strategy to assign books so that the slowest copier can finish at earliest time?
Return the shortest time that the slowest copier spends.
The sum of book pages is less than or equal to 2147483647
Example
Example 1:
Input: pages = [3, 2, 4], k = 2
Output: 5
Explanation:
First person spends 5 minutes to copy book 1 and book 2.
Second person spends 4 minutes to copy book 3.
Example 2:
Input: pages = [3, 2, 4], k = 3
Output: 4
Explanation: Each person copies one of the books.
Challenge
The (NK) Time
Ideas:
You can use half or dynamic programming to solve the question head. But more half the recommended wording of the answer, it is more space-saving idea is simple, easy coding.
For the assumed time limit tm
we can use the idea to judge this greedy k
individuals can complete a copy n
of the book task: as many books given to the same person, determine which finished copy n
number of people in need is not greater than the book k
can be.
And the time limit tm
and the possibility of task (0 or 1) having a monotonic relationship between these two quantities, it is possible to tm
perform a binary search to find the minimum tm
, so that tasks can be accomplished.
public class Solution { /** * @param pages: an array of integers * @param k: An integer * @return: an integer */ public int copyBooks(int[] pages, int k) { if (pages == null || pages.length == 0) { return 0; } int left = 0; int right = Integer.MAX_VALUE; while (left < right) { int mid = left + (right - left) / 2; if (check(pages, k, mid)) { right = mid; } else { left = mid + 1; } } if (check(pages, k, left)) { return left; } return right; } private boolean check(int[] pages, int k, int limit) { int num = 0; int left = 0; for (int item : pages) { if (item > limit) { return false; } if (item > left) { a ++; left = limit; } left -= item; } return num <= k; } }