求数组中连续子序列的最大和
int max(int A[],int begin,int end){ int i,j; int max=0; for(i=0;i<=end;i++){ for(j=i;j<=end;j++){ int m=i;int sum; for(;m<=j;m++){ sum+=A[m]; } if(max<sum) max=sum; sum=0; } } return max; }
上面的算法的时间复杂度是n的立方。
通过分析上面的算法,我们发现求[i,j]的和可以利用[i,j-1]+[j]来求,改进的算法如下:
int max(int A[],int begin,int end){ int i,j; int max=0; for(i=0;i<=end;i++){ int sum=0; for(j=i;j<=end;j++){ sum+=A[j]; if(max<sum) max=sum; } sum=0; } return max; }
这样算法的复杂度就变为n的平方了。
int max(int A[],int begin,int end){ if(end<begin) return 0; if(end==begin) return A[begin]; int m=begin+(end-begin)/2; int sum,lmax,rmax; int i=m;sum=0;lmax=0; for(;i>=begin;i--){ sum+=A[i]; if(sum>lmax) lmax=sum; } i=m+1;sum=0;rmax=0; for(;i<=end;i++){ sum+=A[i]; if(sum>rmax) rmax=sum; } int left=max(A,begin,m); int right=max(A,m+1,end); int max_sum=lmax+rmax; if(max_sum<left) max_sum=left; if(max_sum<right) max_sum=right; return max_sum; }
上面的算法利用了二分 思想,k=(i+j)/2;分为(i,k)和(k+1,j)两部分,那么max要么在(i,k)要么在(k+1,j)要么在(i,j)中。、
如果是第三种情况,那么(i,k)是从右往左算最大值,(k+1,j)是从左往右算最大值。
时间复杂度为nlogn.
接下来是在线性时间内结束的方法:
int max(int A[],int begin,int end){ int max_sofar=0; int maxendinghere=0; int i=begin; for(;i<=end;i++){ if((maxendinghere+A[i])>0) maxendinghere=maxendinghere+A[i]; else maxendinghere=0; if(max_sofar<maxendinghere) max_sofar=maxendinghere; } return max_sofar; }
但是这个算法有个使用范围,就是最大值要大于0。
浙公网安备 33010602011771号