LeetCode410. Split Array Largest Sum(分割数组的最大值)

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.

题目:分割数组的最大值。给定一个均为非负元素的数组nums和数m,将nums划分为m个子序列,使得这m个子序列的和的最大值在所有可能的切分方法中最小。

思路:二分法。假设子序列的数量m是不确定的,那么如果m=1,我们知道返回的值就是整个序列的和nums_sum;如果m=nums.size(),那么子序列中的和的最大值就是nums中的最大值nums_max。因此我们可以知道我们要求的这个最大值一定是在[nums_max, nums_sum]范围内的,记为[l,r]。使用二分法假设最后的这个最大值是max_val = l + (r - l)/2,在进行nums数组的切分时,我们使得每个子串的和都小于等于max_val,按照这样的分法,判断子串的数目是否等于题目中的输入要求个数m,如果小于等于m,说明我们选择的这个max_val还可以更小,更新右边界r;如果子串个数大于m,说明我们的这个max_val太小,更新左边界l

工程代码下载

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        long nums_sum = 0;
        int nums_max = 0;
        for(auto item : nums){
            nums_sum += item;
            nums_max = max(nums_max, item);
        }

        if(m == 1) return nums_sum;
        long l = nums_max, r = nums_sum;
        while(l <= r){
            long mid = l + (r - l)/2;
            if(canSplit(nums, m, mid))
                r = mid - 1;
            else
                l = mid + 1;
        }
        return (int)l;
    }
private:
    bool canSplit(vector<int>& nums, int m, long max_sum){
        long cur_sum = 0;
        int cnt = 1;
        for(auto num : nums){
            cur_sum += num;
            if(cur_sum > max_sum){
                cur_sum = num;
                ++cnt;
                if(cnt > m)
                    return false;
            }
        }
        return true;
    }
};

你可能感兴趣的:(leetcode)