版权声明:本文为博主原创文章,欢迎转载!转载请保留原博客地址。 https://blog.csdn.net/grllery/article/details/88082201
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;
}
};