LintCode:Maximum Subarray III

来源:互联网 发布:网络运营商区别 编辑:程序博客网 时间:2024/05/22 09:03

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">题目:</span>

Maximum Subarray III

45:00

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

0 0