求解最大连续子序列和问题
解法1:maxSubSum1(a,n)算法中用三重循环来穷举所有的连续子序列,计算它们的和,时间复杂度为T(n) = O(n^3)。
1 long maxSubSum1(int a[],int n) 2 { 3 int i,j,k; 4 long maxSum = a[0],thisSum; 5 for(i = 0;i < n;i++) 6 { 7 for(j = i;j < n;j++)//两重循环穷举所有连续子序列 8 { 9 thisSum = 0; 10 for(k = i;k <= j;k++) 11 { 12 thisSum += a[k]; 13 } 14 if(thisSum > maxSum)maxSum = thisSum; 15 } 16 } 17 return maxSum;//将maxSum的值返回给函数结果 18 }
解法2:改进前面的解法,再求两个相邻子序列之和时,它们之间是关联的,在前者计算出来后,求后者时只需在前者的基础上加上一位数就是后者的连续子序列之和,不需要每次都重复计算,从而提高了算法的效率。时间复杂度T(n) = O(n^2)。
1 long maxSubSum2(int a[],int n) 2 { 3 int i,j; 4 long maxSum = a[0],thisSum; 5 for(i = 0;i <= n;i++) 6 { 7 thisSum = 0; 8 for(j = i;j < n;j++) 9 { 10 thisSum += a[j]; 11 if(thisSum > maxSum)maxSum = thisSum; 12 } 13 } 14 return maxSum; 15 }
解法3:进一步改进解法2,如果扫描中遇到负数,当前子序列和thisSum将会减小,若thisSum为负数,表明前面扫描的子序列已经可以抛弃了,则放弃这个子序列,重新开始下一个子序列的分析,并置thisSum为0。若这个子序列和不断增加,那么最大子序列和也不断增加。时间复杂度T(n) = O(n)。
1 int maxSubSum3(int a[],int n) 2 { 3 int i,maxSum = 0,thisSum = 0; 4 for(i = 0;i < n;i++) 5 { 6 thisSum += a[i]; 7 if(thisSum < 0) 8 thisSum = 0; 9 if(maxSum < thisSum) 10 maxSum = thisSum; 11 } 12 return maxSum; 13 }
昨天听算法设计课时听到这些思想我感觉到了算法的美好,所有的程序源码在下面,感兴趣的小伙伴可以试试。
1 #include <stdio.h> 2 long maxSubSum1(int a[],int n)//解法1 3 { 4 int i,j,k; 5 long maxSum = a[0],thisSum; 6 for(i = 0;i < n;i++) 7 { 8 for(j = i;j < n;j++)//两重循环穷举所有连续子序列 9 { 10 thisSum = 0; 11 for(k = i;k <= j;k++) 12 { 13 thisSum += a[k]; 14 } 15 if(thisSum > maxSum)maxSum = thisSum; 16 } 17 } 18 return maxSum;//将maxSum的值返回给函数结果 19 } 20 long maxSubSum2(int a[],int n)//解法2 21 { 22 int i,j; 23 long maxSum = a[0],thisSum; 24 for(i = 0;i <= n;i++) 25 { 26 thisSum = 0; 27 for(j = i;j < n;j++) 28 { 29 thisSum += a[j]; 30 if(thisSum > maxSum)maxSum = thisSum; 31 } 32 } 33 return maxSum; 34 } 35 int maxSubSum3(int a[],int n)//解法3 36 { 37 int i,maxSum = 0,thisSum = 0; 38 for(i = 0;i < n;i++) 39 { 40 thisSum += a[i]; 41 if(thisSum < 0) 42 thisSum = 0; 43 if(maxSum < thisSum) 44 maxSum = thisSum; 45 } 46 return maxSum; 47 } 48 /*主函数*/ 49 int main() 50 { 51 int a[] = {-2,11,-4,13,-5,-2},n = 6; 52 int b[] = {-6,2,4,-7,5,3,2,-1,6,-9,10,-2},m = 12; 53 printf("解法1:a序列的最大连续子序列和:%ld\n",maxSubSum1(a,n)); 54 printf("解法1:b序列的最大连续子序列和:%ld\n",maxSubSum1(b,m)); 55 printf("解法2:a序列的最大连续子序列和:%ld\n",maxSubSum2(a,n)); 56 printf("解法2:b序列的最大连续子序列和:%ld\n",maxSubSum2(b,m)); 57 printf("解法3:a序列的最大连续子序列和:%ld\n",maxSubSum3(a,n)); 58 printf("解法3:b序列的最大连续子序列和:%ld\n",maxSubSum3(b,m)); 59 }
程序源代码