标签:
The subarray should contain at least one number.
Given the array A= [−2,2,−3,4,−1,2,1,−5,3]
, the contiguous subarray[4,−1,2,1]
has the largest sum = 6
.
分析:
对于A[i]来讲,为了使得subarray最大,那么A[i]前的值必须要大于1,如果小于0,我们需要从A[i]开始重新,那么subarray的新起点就可能是A[i].
1 public class Solution { 2 /** 3 * @param nums: A list of integers 4 * @return: A integer indicate the sum of max subarray 5 */ 6 public int maxSubArray(int[] nums) { 7 if (nums == null || nums.length == 0) return 0; 8 int tempMax = nums[0]; 9 int max = nums[0]; 10 11 for (int i = 1; i < nums.length; i++) { 12 if (tempMax > 0) { 13 tempMax += nums[i]; 14 } else { 15 tempMax = nums[i]; 16 } 17 max = Math.max(tempMax, max); 18 } 19 return max; 20 } 21 }
这是一道非常经典的动态规划的题目,用到的思路我们在别的动态规划题目中也很常用,以后我们称为”局部最优和全局最优解法“。
基本思路是这样的,在每一步,我们维护两个变量,一个是全局最优,就是到当前元素为止最优的解是,一个是局部最优,就是必须包含当前元素的最优的解。接下来说说动态规划的递推式(这是动态规划最重要的步骤,递归式出来了,基本上代码框架也就出来了)。假设我们已知第i步的global[i](全局最优)和local[i](局部最优),那么第i+1步的表达式是:
local[i+1]=Math.max(A[i], local[i]+A[i]),就是局部最优是一定要包含当前元素,所以不然就是上一步的局部最优local[i]+当前元素A[i](因为local[i]一定包含第i个元素,所以不违反条件),但是如果local[i]是负的,那么加上他就不如不需要的,所以不然就是直接用A[i];
global[i+1]=Math(local[i+1],global[i]),有了当前一步的局部最优,那么全局最优就是当前的局部最优或者还是原来的全局最优(所有情况都会被涵盖进来,因为最优的解如果不包含当前元素,那么前面会被维护在全局最优里面,如果包含当前元素,那么就是这个局部最优)。
接下来我们分析一下复杂度,时间上只需要扫描一次数组,所以时间复杂度是O(n)。空间上我们可以看出表达式中只需要用到上一步local[i]和global[i]就可以得到下一步的结果,所以我们在实现中可以用一个变量来迭代这个结果,不需要是一个数组,也就是如程序中实现的那样,所以空间复杂度是两个变量(local和global),即O(2)=O(1)。
代码如下:
1 public int maxSubArray(int[] A) { 2 if(A==null || A.length==0) 3 return 0; 4 int global = A[0]; 5 int local = A[0]; 6 for(int i=1;i<A.length;i++) 7 { 8 local = Math.max(A[i],local+A[i]); 9 global = Math.max(local,global); 10 } 11 return global; 12 }
Given an array of integers, find two non-overlapping subarrays which have the largest sum. The number in each subarray should be contiguous. Return the largest sum.
The subarray should contain at least one number.
Example
For given [1, 3, -1, 2, -1, 2]
, the two subarrays are [1, 3]
and [2, -1, 2]
or [1, 3, -1, 2]
and [2]
, they both have the largest sum 7
.
分析:
既然要有两个不重合的subarray,如果左边一个确定了,右边那个一定是在array的右边部分找。
1 public class Solution { 2 /** 3 * @param nums: A list of integers 4 * @return: An integer denotes the sum of max two non-overlapping subarrays 5 * cnblogs.com/beiyeqingteng/ 6 */ 7 public int maxTwoSubArrays(ArrayList<Integer> nums) { 8 if (nums == null || nums.size() == 0) return 0; 9 int[] forwardMax = new int[nums.size()]; 10 11 forwardMax[0] = nums.get(0); 12 13 for (int i = 1; i < nums.size(); i++) { 14 if (forwardMax[i - 1] > 0) { 15 forwardMax[i] = nums.get(i) + forwardMax[i - 1]; 16 } else { 17 forwardMax[i] = nums.get(i); 18 } 19 } 20 21 int[] backwardMax = new int[nums.size()]; 22 23 backwardMax[backwardMax.length - 1] = nums.get(nums.size() - 1); 24 for (int i = backwardMax.length - 2; i >= 0; i--) { 25 if (backwardMax[i + 1] > 0) { 26 backwardMax[i] = nums.get(i) + backwardMax[i + 1]; 27 } else { 28 backwardMax[i] = nums.get(i); 29 } 30 } 31 32 int[] rightMax = new int[nums.size()]; 33 34 rightMax[rightMax.length - 1] = backwardMax[backwardMax.length - 1]; 35 for (int i = rightMax.length - 2; i >= 0; i--) { 36 if (backwardMax[i] >= rightMax[i + 1]) { 37 rightMax[i] = backwardMax[i]; 38 } else { 39 rightMax[i] = rightMax[i + 1]; 40 } 41 } 42 43 int max = forwardMax[0] + rightMax[1]; 44 for (int i = 1; i < nums.size() - 1; i++) { 45 max = Math.max(max, forwardMax[i] + rightMax[i + 1]); 46 } 47 return max; 48 } 49 }
转载请注明出处:cnblogs.com/beiyeqingteng/
标签:
原文地址:http://www.cnblogs.com/beiyeqingteng/p/5632661.html