Given an array of integers and a number k, find k non-overlapping
subarrays which have the largest sum.
The number in each subarray should be contiguous.
ExampleGiven [-1,4,-2,3,-2,3]
, k=2
, return 8
lintcode网址:http://www.lintcode.com/en/problem/maximum-subarray-iii/
非常难,看了好几个答案都看不懂,最后看到这篇才有了思路,但是代码好像有地方不太对,但是大致了解了按照动规的步骤来就出来了。 必须得写一篇记录一下。
http://hehejun.blogspot.com/2015/01/lintcodemaximum-subarray-iii.html
最重要的思路:
维护一个 globalMax [ k+1 ] [ len+1 ] 的矩阵, globalMax [ i ] [ j ] 代表了前 j 个数中取 i 个 subarray 得到的最大和, 注意这里第 j 个数不一定被包括。
一个 int 类型: localMax, 每次写第 globalMax 的 第 i 行 第 j 列时用到的, 记录前 j 个数中取 i 个 subarray 得到的最大和, 但包括第 j 个数。
... ...
... globalMax [ i-1 ] [ j-1 ] | globalMax [ i-1 ] [ j ]
... globalMax [ i ] [ j-1 ] | globalMax [ i ] [ j ]
... ...
成为 globalMax [ i ] [ j ] 的 candidates:
1. 第 j 个数没有被包括:globalMax [ i ] [ j-1 ]
2. 第 j 个数被包括:
2a. 第 j 个数单独做一个 subarray: globalMax[ i - 1 ] [ j-1 ] + nums.get( j-1 )
2b. 第 j 个数并入之前的subarray:localMax' + nums.get( j-1 )
哦了,上代码,代码没多少, 注释很多。
// DP
// globalMax[i][j]:max sum of i subarrays from the first j elements, jth element may not be included
// localMax: max sum of i subarrays from the first j elements, jth element included
// transfer function:
// localMax = Max(sum(jth element merged in the last subarray), sum(jth element alone is a subarray))
// localMax = Max(localMax' + nums.get(j-1), globalMax[i-1][j-1]+nums.get(j-1))
// globalMax = Max(jth element is not include, jth element is included)
// globalMax = Max(globalMax[i][j-1], localMax)
public class Solution {
/**
* @param nums: A list of integers
* @param k: An integer denote to find k non-overlapping subarrays
* @return: An integer denote the sum of max k non-overlapping subarrays
*/
public int maxSubArray(ArrayList<Integer> nums, int k) {
// write your code
if(nums == null || k == 0){return 0;}
int len = nums.size();
if(len < k){return 0;}
// globalMax[i][j]:max sum of i subarrays from the first j elements
// the last element nums[j-1] may not be included
int [][] globalMax = new int[k+1][len+1];
// initialize first row to 0s, because selecting 0 subarrays
for(int i = 0; i <= len; i++){
globalMax[0][i] = 0;
}
// initialize globalMax[i][i] = SUM_nums[0~i-1], i.e. first i elements
for(int i = 1; i <= k; i++){
int sum = 0;
for(int j = 0; j < i; j++){
sum += nums.get(j);
}
globalMax[i][i] = sum;
}
for(int i = 1; i <=k; i++){
// localMax is the max sum of i subarrays from the first j elements
// but the last element must be included
// initialize localMax as i-1 subarrays + nums.get(i-1) as a the last subarray
int localMax = globalMax[i][i];
for(int j = i+1; j <= len; j++){
localMax = Math.max(localMax+nums.get(j-1), globalMax[i-1][j-1]+nums.get(j-1));
globalMax[i][j] = Math.max(globalMax[i][j-1], localMax);
}
}
return globalMax[k][len];
}
}