Quesition
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
思路一(蛮力法)
代码
public class Solution {
public int maxSubArray(int[] nums) {
int maxSum = nums[0];
int curSum = 0;
for(int i = 0;i < nums.length;i++){
for(int j = i;j < nums.length;j++){
for(int k = i;k <= j;k++){
curSum += nums[k];
}
if(curSum > maxSum)
maxSum = curSum;
curSum = 0;
}
}
return maxSum;
}
}
结果及分析
超时了
思路二(七月的方法,动态规划)
事实上可以令currSum是以当前元素结尾的最大连续数组的和,maxSum是全局的最大子数组的和,当从前往后遍历时,对第j个元素有两种选择,要么放入当前的数组,要么作为数组的第一个元素;如currSum > 0,则把当前元素放入子序列;如果currSum < 0,则把currSum置为当前元素;
代码
public class Solution {
public int maxSubArray(int[] nums) {
int maxSum = nums[0];
int curSum = 0;
for(int right = 0;right < nums.length;right++){
if(curSum > 0)
curSum += nums[right];
else
curSum = nums[right];
if(curSum > maxSum)
maxSum = curSum;
}
return maxSum;
}
}
结果及分析
时间复杂度为O(n),空间复杂度为O(1),已经是最优的结果了。
二刷解法I
跟七月的解法差不多,如果当前sum为负,就sum置为当前的数组元素,如果为证则加上当前数组元素。其中隐含的原理是如果前面的和为负就没有必要再继续加上去了,加上去也是越来越小。这实际上是一种动态规划的思想。
code
public class Solution {
public int maxSubArray(int[] nums) {
if(nums == null || nums.length == 0)
return 0;
int sum = 0;
int maxSum = Integer.MIN_VALUE;
for(int i = 0;i < nums.length;i++){
if(sum < 0)
sum = nums[i];
else
sum += nums[i];
maxSum = Math.max(maxSum,sum);
}
return maxSum;
}
}
二刷解法II
this problem was discussed by Jon Bentley (Sep. 1984 Vol. 27 No. 9 Communications of the ACM P885)
the paragraph below was copied from his paper (with a little modifications)
algorithm that operates on arrays: it starts at the left end (element A[1]) and scans through to the right end (element A[n]), keeping track of the maximum sum subvector seen so far. The maximum is initially A[0]. Suppose we’ve solved the problem for A[1 .. i - 1]; how can we extend that to A[1 .. i]? The maximum
sum in the first I elements is either the maximum sum in the first i - 1 elements (which we’ll call MaxSoFar), or it is that of a subvector that ends in position i (which we’ll call MaxEndingHere).
MaxEndingHere is either A[i] plus the previous MaxEndingHere, or just A[i], whichever is larger.
CODE
public static int maxSubArray(int[] A) {
int maxSoFar=A[0], maxEndingHere=A[0];
for (int i=1;i<A.length;++i){
maxEndingHere= Math.max(maxEndingHere+A[i],A[i]);
maxSoFar=Math.max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}