Maximum Subarray III

Question: 

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.

Return the largest sum.

 
Example:

Given [-1,4,-2,3,-2,3]k=2, return 8

 
Analysis:
这题属于动态规划里比较难的一题。首先定义状态,f[i][j]表示:在前i个元素中取出j个不重叠的子数组的和的最大值(也就是要将前i个元素组成的数组划分成j个部分,每个部分求最大子数组,然后相加)。状态定义好了之后,需要找到状态之间的关联,也就是求动态转移方程。可以将f[i][j]拆分成两部分来看,第一部分是f[x][j - 1],x为j - 1~ i - 1之间的任意值,表示前x个元素中取j - 1个子数组的和的最大值。第二部分是[x, x + 1, ..., i - 1]数组,求这个数组的maximum subarray(可以理解为在数组[0, 1, ..., x - 1, x, ..., i - 1]中任意切一刀,分成两部分。index为x - 1的地方就是那一刀切的地方,第一部分是[0, 1, ..., x - 1],第二部分是[x, x + 1, ..., i - 1])。由此得到动态转移方程为:f[i][j] = f[x][j - 1] + maxSubarray([x, x + 1, ..., i - 1])。求max subarray的方法可以参考maximum subarray那道题。
 
Code:
 1 public class Solution {
 2     /**
 3      * @param nums: A list of integers
 4      * @param k: An integer denote to find k non-overlapping subarrays
 5      * @return: An integer denote the sum of max k non-overlapping subarrays
 6      */
 7     public int maxSubArray(int[] nums, int k) {
 8         int length = nums.length;
 9         if(length < k) {
10             return 0;
11         }
12         
13         //f[i][j] means max sum of j subarrays from nums[0] to nums[i - 1], i from 0 ~ length, 
14         //j from 0 ~ k
15         int[][] f = new int[length + 1][k + 1];
16         for(int i = 0; i <= length; i++) {
17             f[i][0] = 0;
18         }
19         for(int j = 0; j <= k; j++) {
20             f[0][j] = 0;
21         }
22         
23         //i depends on j, so first start loop of j
24         for(int j = 1; j <= k; j++) {
25             for(int i = j; i <= length; i++) {
26                 f[i][j] = Integer.MIN_VALUE;
27                 int sum = 0, max = Integer.MIN_VALUE, minSum = 0;
28                 for(int x = i - 1; x >= j - 1; x--) {
29                     sum += nums[x];
30                     max = Math.max(max, sum - minSum);
31                     minSum = Math.min(minSum, sum);
32                     
33                     f[i][j] = Math.max(f[i][j], f[x][j - 1] + max);
34                 }
35             }
36         }
37         
38         return f[length][k];
39     }
40 }

 

 

Complexity:
时间复杂度是O(k * n^2), n是nums数组的长度,k是题目要求的subarrays的个数。空间复杂度就是新开的f二维数组,O(n * k)。
 

参考:

https://wxx5433.gitbooks.io/interview-preparation/content/part_ii_leetcode_lintcode/dp/maximum_subarray_iii.html 

posted on 2016-01-18 14:43  BillZ  阅读(310)  评论(0编辑  收藏  举报

导航