410. Split Array Largest Sum

问题描述:

Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

Note:
If n is the length of array, assume the following constraints are satisfied:

  • 1 ≤ n ≤ 1000
  • 1 ≤ m ≤ min(50, n)

Examples:

Input:
nums = [7,2,5,10,8]
m = 2

Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.

解题思路:

刚看到这道题没有一点思路,于是参考了HaoxiangXu的解法

它的解法讲得非常清晰透彻了。

这里用到了二分法和贪婪算法来一起做。

首先将问题分成了两个子问题:

1.  给出一个数组arr,给定分割数m以及每个组的最大和MAX,能否用最多m个分割将数组分成子数组和不超过MAX的子数组?

2. 给出一个下界left,和一个上界right,一个未知的bool数组(B)以及一个使用i作为输入并且告诉你B[i]是否为true的API。若我们知道,一定存在一个下标k,使得i<k 时,B[i] 为false, i >= k时, B[i]为true。 找到k的最快的方式是什么?

对于第一个问题, 我们可以使用贪婪算法来解答。在组中加入当前数字n,判断当前的组合是否超出MAX,若超出,则将当前数字作为新的组的起点,更新新的组和为当前数字n,并且分割数减一(因为开始了新的组,我们需要用一个分割来分割两个组)。

注意此时要判断分割数是否小于0,若分割数小于0,则代表当前分割数无法分割出组和不超过MAX的子数组们。

对于第二个问题,我们很容易想到二分搜索。

回归到当前问题,我们需要寻找上界(right)和下界(left)。

最小的分割为只有一个元素,最大的分割为原数组,所以left = max(arr), right = sum(arr);

给大神跪了ORZ

代码:

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        long long left = 0, right = 0;
        for(int n : nums){
            left = max(left, (long long)n);
            right += (long long)n;
        }
        while(left < right){
            long long mid = left + (right - left)/2;
            if(isWork(nums, m-1, mid)) right = mid;
            else left = mid+1;
        }
        return left;
    }
private:
    bool isWork(vector<int>& nums, int cuts, long long max){
        int acc = 0;
        for(int n : nums){
            if(n > max) return false;
            if(acc + n <= max) acc += n;
            else{
                acc = n;
                cuts--;
                if(cuts < 0) return false;
            }
        }
        return true;
    }
};
原文地址:https://www.cnblogs.com/yaoyudadudu/p/9315822.html