Copy Books

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;
    }
}

  

Guess you like

Origin www.cnblogs.com/FLAGyuri/p/12078040.html