problem:
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.
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
thinking:
(1)这道题解法特别多:
方法1:将每个数和后一个数字相加,得到一个正负分布的序列,正数项对最大和子序列实用,作比較就可以
方法2:暴力匹配,两层循环,调用max()函数。时间复杂度O(n*n),也能够算出结果,可是提交超时
方法3:採用DP。时间复杂度O(n)
方法4:分治法。时间复杂度为nlog(n)
(2)本人实现了方法3 和方法4
code:
DP 法:
class Solution { public: int maxSubArray(int A[], int n) { int sum=A[0]; int maxsum=A[0]; for(int i=1;i<n;i++) { if(sum<0) //DP核心 sum=0; sum+=A[i]; maxsum=max(sum,maxsum); } return maxsum; } };
分治法:
class Solution { public: int maxSubArray(int A[], int n) { int ret=maxsub(A,0,n-1); return ret; } protected: int maxsub(int A[], int start, int end) { int max_left=INT_MIN,max_mid=INT_MIN,max_right=INT_MIN; if(start==end) return A[start]; if(start+1==end) { int a=max(A[start],A[end]); return a>(A[start]+A[end])?a:(A[start]+A[end]); } int mid=(start+end)/2; int tmp_sum=A[mid]; max_mid=tmp_sum; int i=mid-1; int j=mid+1; while(i>=start) //难点在于当连续最大和子序列分布在mid的一側或两側时,怎么处理 { tmp_sum+=A[i]; i--; max_mid=max(max_mid,tmp_sum); } if(max_mid>A[mid]) //推断是处于两側,还是处于一側 tmp_sum=max_mid; else tmp_sum=A[mid]; while(j<=end) { tmp_sum+=A[j]; j++; max_mid=max(max_mid,tmp_sum); } max_left=max(max_left,maxsub(A,start,mid-1));//二分轮廓 max_right=max(max_right,maxsub(A,mid+1,end)); int tmp_max = max(max_left,max_right); return max_mid>tmp_max?max_mid:tmp_max; } };