Maximum Subsequence Sum
问题描述
给定K个整数组成的序列{ N1, N2, …, NK },“连续子列”被定义为{ Ni, Ni+1, …, Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
算法解答
算法一:多层遍历,时间复杂度O(n3)
int MaxSubeqSum1(int a[],int n) { int thissum=0,maxsum=0; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { for(int k=i;k<=j;k++) { thissum+=a[k]; } if(thissum>maxsum) maxsum=thissum; thissum=0; } } return maxsum; }
算法二:去掉最内层循环,时间复杂度O(n2)
int MaxSubeqSum2(int a[],int n) { int thissum=0,maxsum=0; for(int i=0;i<n;i++) { for(int j=i;j<n;j++) { thissum+=a[j]; if(thissum>maxsum) maxsum=thissum; } thissum=0; } return maxsum; }
算法三:分而治之,时间复杂度O(nlogn),最大子序列和必在左子列,右子列和跨界子序列
int MaxSubeqSum3(int a[],int left,int right) { if(left==right) { return a[left]; }//递归基 int middle = (left+right)/2; int lsum=MaxSubeqSum3(a,left,middle); int rsum=MaxSubeqSum3(a,middle+1,right);//递归寻找两边子序列最大和 /* 再分别找左右跨界最大子列和*/ int leftmaxsum = 0; int leftthissum = 0; for(int i=middle;i>=left;i--){ //应该从边界出发向左边找 leftthissum += a[i]; if(leftmaxsum < leftthissum) leftmaxsum = leftthissum; } int rightmaxsum = 0; int rightthissum = 0; for(int i=middle+1;i<=right;i++){ // 从边界出发向右边找 rightmaxsum += a[i]; if(rightmaxsum < rightthissum) rightmaxsum = rightthissum; } return max(leftmaxsum+rightmaxsum,max(lsum,rsum)); }//分治递归
算法四:贪心算法,时间复杂度O(n),每次只计算出正序列和,最后总和最大
int MaxSubeqSum4(int a[],int n) { int thissum=0,maxsum=0; for(int i=0;i<n;i++) { thissum+=a[i]; if(thissum>maxsum) maxsum=thissum; else if(thissum<0) thissum=0; } return maxsum; }//贪心算法
主函数测试代码
int main(void) { int n = 0; scanf("%d",&n); int *number=(int*)malloc(sizeof(n)); if(!number) { printf("内存分配失败\n"); return NULL; } for(int i =0;i<n;i++) { scanf("%d",&number[i]); } printf("maxsum:%d\n",MaxSubeqSum3(number,0,n-1)); free(number); number=NULL; getchar(); return 0; }