给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组。设计一个算法使得这 m 个子数组各自和的最大值最小。
注意:
数组长度 n 满足以下条件:
- 1 ≤ n ≤ 1000
- 1 ≤ m ≤ min(50, n)
示例:
输入: nums = [7,2,5,10,8] m = 2 输出: 18 解释: 一共有四种方法将nums分割为2个子数组。 其中最好的方式是将其分为[7,2,5] 和 [10,8], 因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。
这一道题目使用二分的方法,枚举这个各个数组的最大值和的最小值。时间复杂度是O(NlogN), 在写check函数时需要特判掉特殊情况。用int枚举就能解决。
/*
* @lc app=leetcode.cn id=410 lang=java
*
* [410] 分割数组的最大值
*
* 枚举这个最小值
*/
class Solution {
public int splitArray(int[] nums, int m) {
int left =1, right = Integer.MAX_VALUE;
while(left<=right){
int mid = left + (right-left)/2;
if(check(nums,m,mid)) right=mid-1;
else left = mid+1;
}
return left;
}
boolean check(int[] nums, int m, int k){
int sum = 0,count=1;
for(int i=0;i<nums.length;i++){
if(nums[i]>k) return false; // 特殊情况
if(sum+nums[i]<=k) sum+=nums[i];
else {
sum = nums[i];
count++;
}
}
return count<=m;
}
}