原题目https://leetcode-cn.com/problems/split-array-largest-sum/:
思路一:
采用动态规划,f[i][j]表示把i个字符拆成j个组所得到的的结果,那么容易得到转移方程如下:
思路二:
采用二分查找的方法,左边界为数组元素的最大值,有边界为数组的和,判断根据mid 分割的数组的数目是否<=m。如果满足right=mid-1.否则left = mid+1。
根据mid分割的方法:使用cnt记录子数组和小于mid的个数。
代码:
class Solution {
public:
int splitArray(vector<int>& nums, int m) {
int n = nums.size();
vector<vector<long long >> dp(n+1,vector<long long>(m+1,LLONG_MAX));
vector<long long> pre(n+1,0);
for(int i=0;i<n;i++){
pre[i+1] = pre[i] + nums[i];
}
dp[0][0] = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=min(i,m);j++){
for(int k=0;k<i;k++){
dp[i][j] = min(dp[i][j], max(dp[k][j-1] , pre[i]-pre[k]));
}
}
}
return dp[n][m];
}
};
class Solution {
public:
bool check(vector<int> &nums, int mid, int m){
int cnt = 1;
long long sum = 0;
for(int i:nums){
if(sum + i > mid){
cnt ++; sum = i;
}
else{
sum += i;
}
}
return cnt <= m;
}
int splitArray(vector<int>& nums, int m) {
long long left=0,right=0;
for(int i:nums){
if(left < i) left = i;
right += i;
}
while(left<=right){
long long mid = (right+left) >> 1;
if(check(nums,mid,m)){
right = mid-1;
}
else{
left = mid+1;
}
}
return left;
}
};