当前位置:   article > 正文

分治算法之最大子段和_最大子段和问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求

最大子段和问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该

最大子段和: 对于n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n 。本文中取n=20,a[i]属于[-20,20].

  1. #include<iostream>
  2. #include <cstdlib>
  3. #include<ctime>
  4. #include<cstdlib>
  5. using namespace std;
  6. int maxsum(int a[],int left,int right)
  7. {
  8. int sum=0;
  9. if(left==right)
  10. sum = a[left] > 0 ? a[left] : 0;
  11. else
  12. {
  13. int center=(left+right)/2;
  14. int s1=0;
  15. int lefts=0;
  16. for(int i=center;i>=left;i--)
  17. {
  18. lefts+=a[i];
  19. if(lefts>s1) s1=lefts;
  20. }
  21. int s2=0;
  22. int rights=0;
  23. for(int j=center+1;j<=right;j++)
  24. {
  25. rights+=a[j];
  26. if(rights>s2) s2=rights;
  27. }
  28. int leftsum=maxsum(a,left,center);
  29. int rightsum=maxsum(a,center+1,right);
  30. sum=s1+s2;
  31. if(sum<leftsum) sum=leftsum;
  32. if(sum<rightsum) sum=rightsum;
  33. }
  34. return sum;
  35. }
  36. int main()
  37. {
  38. int maxsum(int a[],int left,int right);
  39. int i;
  40. const int n=20;
  41. int a[n]={0};
  42. cout<<"生成随机序列:"<<endl;
  43. srand(time(0));
  44. for(i=0;i<n;i++)
  45. {
  46. a[i]=rand() % (20+20+1)-20;
  47. cout<<a[i]<<' ';
  48. }
  49. cout<<endl;
  50. cout<<"最大子段和为"<<maxsum(a,0,n-1);
  51. return 0;
  52. }

补充


复杂性分析:

将a[0:n]分成a[0:n/2]和a[n/2+1:n],则a[n]的最大字段和有三种情况:

(1).a[0:n]的最大子段和与a[0:n/2]的最大子段和相同.

(2)a[0:n]的最大子段和与a[n/2+1:n]的最大子段和相同.

(1)(2)时间复杂度为O(logn).

(3)a[0:n]的最大子段和为i到j的累加,其中0<=i<=n/2,n/2+1<=j<=n.

时间复杂度T(n)=2T(n/2)+O(n) ,所以T(n)=O(nlogn).

综上,最大子段和的时间复杂度为O(nlogn)。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/951940
推荐阅读
相关标签
  

闽ICP备14008679号