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

O(nk) time

思路:

可以使用二分或者动态规划解决这道题目. 不过更推荐二分答案的写法, 它更节省空间, 思路简洁, 容易编码.

对于假定的时间上限 tm 我们可以使用贪心的思想判断这 k 个人能否完成复印 n 本书的任务: 将尽可能多的书分给同一个人, 判断复印完这 n 本书需要的人数是否不大于 k 即可.

扫描二维码关注公众号,回复: 8267959 查看本文章

而时间上限 tm 与可否完成任务(0或1)这两个量之间具有单调性关系, 所以可以对 tm 进行二分查找, 查找最小的 tm, 使得任务可以完成.

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) {
                num++;
                left = limit;
            }
            left -= item;
        }
        return num <= k;
    }
}

  

猜你喜欢

转载自www.cnblogs.com/FLAGyuri/p/12078040.html