Maximum Subarray III

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.

Example

Given [-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];
    }
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值