结对成员:李金吉,赵天
要求:
实现查找到一个数组的子数组中元素的和的最大值,比如说:
int a[]={9,8,-3,19,-30}
这时我们发现9+8+-3+19 这个子数组的和是最大的。
想法:
如果是人脑的做法,无非从两个开始比较,将两个两个的和计算出来;再三个三个比较,将三个的和计算出来.....
用计算机实现:
可以从数组中第一个开始,设置一个辅助数组记录子数组的和;
如图:有个一个数组arr[]; a[0]~a[n]是辅助数组;
a[0]=arr[0];
a[1]=arr[0]+arr[1];
a[2]=arr[0]+arr[1]+arr[2];
a[3]=arr[0]+arr[1]+arr[2]+a[3];
....
a[7]=arr[1];
a[8]=arr[1]+arr[2];
a[9]=arr[1]+arr[2]+arr[3];
....
可以发现a[0]=arr[0];
a[1]=a[0]+arr[2];
...
a[n-1]=a[n-2]+arr[n-1];
...
通过这种方法可以将这个数组的每个子数组的元素和都遍历出来:
具体代码及单元测试:
#include<iostream> #define null -858993460 using namespace std; void main() { int arr[]={8,9,10,-1,20,-30,4}; int arr2[]={-9,-1,-4,-123}; int arr3[]={0}; int arr4[]={7,9,8}; int arr5[3]; int test(int list[],int length); cout<<test(arr,7)<<endl; cout<<test(arr2,4)<<endl; cout<<test(arr3,1)<<endl; cout<<test(arr4,3)<<endl; cout<<test(arr5,0)<<endl; } int test(int list[],int length) { int a[100]={0},x=0; int max; int i,j; int k=0; if(list==NULL||length==0) { cout<<"error!inter is null!"; return 0; } for(i=0;i<length;i++) { a[k]=list[i]; for(j=i;j<length;j++) { a[k+1]=a[k]+list[j+1]; k++; } } max=a[0]; for(i=0;i<k;i++) { if(max<a[i]) { max=a[i]; } } return max; }
这种算法的时间复杂度o(n2)
老师说这种算法的时间复杂度可以达到n,通过查阅资料知道,用2分法遍历可是实现时间复杂度O(nlogn),利用类似数的遍历(递归调用)实现时间复杂度O(n),
//令cursum(i)表示数组下标以i为起点的最大连续下标最大的和,而maxsum(i)表示前i个元素的最大子数组之和。
//那么我们就可以推出下一个maxsum(i+1)应该为cursum(i+1)和maxsum(i)中选取一个最大值。递推式为: cursum(i) = max{A[i],cursum(i-1)+A[i]}; maxsum(i) = max{maxsum(i-1),cursum(i+1)};