LintCode:Maximum Subarray III

题目:

Maximum Subarray III

45:00
 Start

Given an array of integers and a number k, find knon-overlapping subarrays which have the largest sum.

The number in each subarray should be contiguous.

Return the largest sum.


据说这是一道hard题

这两天一直在研究最大子序列的花式变形以及follow up。等due赶完更新一篇最大子序列的总结。Max Subarray感觉还是面试的最爱啊!

这道题最合适的方法就是dp了。其实最难想的也是dp方程。仔细读题求K个不重叠的子序列的最大和。既然求K个不重叠的最大子序列之和。那么仔细想一想第K-1个最大子序列和是怎样一种情况。


K个子序列的最大 其实就是K-1个子序列的最大和加上第K-1个子序列的最后一个数到最后一个数这段数组中的最大子数组。但是问题又来了,第K-1个子数组的最后一个下标是多少呢?刚开始自己也被这个情况所困扰,但是再仔细想一想,第K-1个子数组的一个边界条件是其最后一个数刚好是第K-1个(每个子数组只有一个数并且连续)另外一个边界条件是整个数组的倒数第二个。(不是倒数第一个的原因是要给那个所求的最大子数组留出空间),既然不知道具体的位置,就把所有的可能求一遍取最值吧。所以DP方程可得:


dp[ i ][ j ] =  Max( dp[ p ][ j - 1] + MaxSubArray[ p+1 ][ i ] );     j -1 <= p <=i-1; dp[ i ][ j ]表示在前i个数中取j个子数组的值的Max;



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(int[] nums, int k) {
        // write your code here
        //Dp formula get: dp[i][j] = Max(dp[p][j-1]+MaxSub[p+1][i]) j-1<=p<=i-1
        if(nums == null || nums.length == 0){
            return 0;
        }
        if(k > nums.length){
            return 0;
        }
        
        int[][]dp = new int[nums.length + 1][k + 1];
        dp[0][0] = 0;
        for(int i = 1; i <= nums.length;i++){
            for(int j = 1; j <=k&&j <= i;j++){
                int Max = Integer.MIN_VALUE;
                for(int p = j-1;p <= i-1;p++){
                    Max = Math.max(dp[p][j-1]+MaxSub(nums,p+1,i),Max);
                }
                dp[i][j] = Max;
            }
        }
        return dp[nums.length][k];
    }
    private int MaxSub(int[] nums,int i,int k){
        
        int[]MaxSubHelper = new int[k-i+2];
        MaxSubHelper[0] = 0;
        for(int j = 1;j < MaxSubHelper.length;j++){
            MaxSubHelper[j] = MaxSubHelper[j-1]+nums[i-1+j-1];
        }
        
        int Max = Integer.MIN_VALUE;
        int MaxSum = 0;
        int MinPrice = Integer.MAX_VALUE;
        
        for(int m = 1; m < MaxSubHelper.length;m++){
            MinPrice = Math.min(MinPrice,MaxSubHelper[m-1]);
            MaxSum = MaxSubHelper[m] - MinPrice;
            Max = Math.max(Max,MaxSum);
        }
        
        
        return Max;
        
    }
}


如果K > 数组的长度那么就没有意义了。所以第二个循环添加了一个判断条件作为一个剪纸,防止超时(事实证明确实挺慢的- -)。

你可能感兴趣的:(算法,Java,LintCode)