题目:
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
.
click to show more practice.
分析:给定一整数序列A1, A2,... An (可能有负数),求A1~An的一个子序列Ai~Aj,使得Ai到Aj的和最大
例如:整数序列[−2,1,−3,4,−1,2,1,−5,4]的最大子序列[4,−1,2,1]
的和为6,。
解题思路:
1.我们最容易想到的就是暴力法来求解了,我们先来看看两种穷举法的写法和时间复杂度(分别为O(n^3) 和 O(n^2))
2.我会使用分治法来完成这道题目,复杂度为O(nlogn)
3.我会使用DP的思想来做这道题目,复杂度为O(n)
一、穷举法(暴力)【O(n^3)】
public int maxSubArray(int[] A) { int len = A.length; int max = Integer.MIN_VALUE; //把每种情况都遍历出来,取出最大sum的值 for (int i=0; i<len; ++i){ for (int j=i; j<len; ++j){ int temp = 0; for (int k=i; k<j; ++k){ temp += A[k]; } if (temp > max){ max = temp; } } } return max; }
public int maxSubArray(int[] A) { int len = A.length; int max = Integer.MIN_VALUE; //把每种情况都遍历出来,取出最大sum的值 for (int i=0; i<len; ++i){ int temp = 0; for (int j=i; j<len; ++j){ temp += A[j]; if (temp > max) max = temp; } } return max; }
思路:由于我们知道最大子序列可能存在于A数组的左边,右边,或者一点左边一点右边。
所以我们很容易可以联想到,居然这样我们可以把A数组划分成若干个小的子数组,对子数组求出左边的最大值,和右边的最大值,再求出从中间位置到左边的某个位置的最大值、从中间位置到右边的某个位置的最大值,得到了这四个值之后剩下的我们就可以通过比较得到这个子数组的最大值了。(递归的过程)
public class Solution { public int maxSum(int[] A, int left, int right ) { if( left == right ){ return A[left]; } int center = (left + right) / 2; int maxLeftSum = maxSum( A, left, center); int maxRightSum = maxSum( A, center+1, right); int maxLeft = Integer.MIN_VALUE, tempLeft = 0; int maxRight = Integer.MIN_VALUE, tempRight = 0; for (int i=center; i>=left; --i){ tempLeft += A[i]; if (tempLeft > maxLeft){ maxLeft = tempLeft; } } for (int i=center+1; i<=right; ++i){ tempRight += A[i]; if (tempRight > maxRight){ maxRight = tempRight; } } int maxCenterSum = maxLeft + maxRight; return maxCenterSum > maxLeftSum ? (maxCenterSum > maxRightSum ? maxCenterSum : maxRightSum) : maxLeftSum > maxRightSum ? maxLeftSum : maxRightSum; } public int maxSubArray(int[] A){ int len = A.length; return maxSum(A,0,len-1); } }
四、DP思想解题【O(n)】(这里要怒喷一下,网上好多人都有一份分治法的代码,都是copy来copy去的,但是却不是正确的,这代码是AC过的才发上来的!)
public class Solution { public int maxSubArray(int[] A) { int len = A.length; int max = Integer.MIN_VALUE; int temp = Integer.MIN_VALUE; for (int i=0; i<len; ++i){ if (temp < 0) temp = A[i]; else{ temp += A[i]; } if (temp > max){ max = temp; } } return max; } }