标签:mini 位置 constrain 变量 最大值 bar not 结果 并且
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: Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000. Examples: Input: nums = [7,2,5,10,8] m = 2 Output: 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.
二分法:
public int splitArray(int[] nums, int m) {
long sum = 0;
int max = 0;
for(int num: nums){
max = Math.max(max, num);
sum += num;
}
return (int)binarySearch(nums, m, sum, max);
}
//二分查找
private long binarySearch(int[] nums, int m, long high, long low){
long mid = 0;
while(low < high){
mid = (high + low)/2;
//验证是否满足,也就是这么大的值有可能出现么
if(valid(nums, m, mid)){
high = mid;
}else{
low = mid + 1;
}
}
return high;
}
/**
* 验证这个值是否合法
* */
private boolean valid(int[] nums, int m, long max){
int cur = 0;
int count = 1;
//是否有多余m个片段or区间,大于给定值的max的,如果有了,那么就不合法了,因为这样划分就不止m个,及max太小
for(int num: nums){
cur += num;
if(cur > max){
cur = num;
count++;
if(count > m){
return false;
}
}
}
return true;
}
动归: 最大, 最小, 不能排序, 而且是求区间和的改写, 先考虑用一维动归, dp[m]表示分为m组, 写不出状态转移方程. 并且, 这是最大值最小的问题, 先找最大, 再找最小, 所以用二维数组, 题中就是组数, 和第几个人是变量, 因此dp[m][n] 表示将n个人分为m组的结果值, 这样有了两层外循环, 看递推公式与两层外循环的关系:
dp[m][n] = min (dp[m][n], Un-1 j = m - 1 max(dp[m - 1][j], sum[n] - sum[j]) (内循环多是最后一次分割点位置变化, 和前一次分割的关系 )
因为dp[m - 1][j] 不能直接得到, 所以需要 外循环 动归到dp[m][n], 其实想想也很简单, 只有外循环先建立起来了, 才有内循环的递推公式.
一维状态方程常考虑: 要不要该点,
二维状态方程常考虑: 分割点(与题目的值(sums[j] - sums[k]) 联系最紧密 , 当前分割的次数与前一次数有什么关系
subarray 和的问题常转化为 区间和的问题, (sums[j] - sums[k])
起点的初始化要正常, 中间点的初始化时为了比较(min, max) 等.------知道的初始化正常值, 不知道的初始化为对立值.
public int splitArray(int[] nums, int m) {
int n = nums.length;
int[][] dp = new int[m + 1][nums.length + 1];
int[] sums = new int[n + 1];
for (int i = 1; i <= n; ++i) {
sums[i] = sums[i - 1] + nums[i - 1];
}
for (int i = 0; i <= m; ++i) {
for (int j = 0; j <= n; ++j) {
dp[i][j] = Integer.MAX_VALUE;
}
}
dp[0][0] = 0;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
for (int k = i - 1; k < j; ++k) {
int val = Math.max(dp[i - 1][k], sums[j] - sums[k]);
dp[i][j] = Math.min(dp[i][j], val);
}
}
}
return dp[m][n];
}
标签:mini 位置 constrain 变量 最大值 bar not 结果 并且
原文地址:http://www.cnblogs.com/apanda009/p/7281294.html