【重征算法路】之七:最大子段和算法 (动态规划)

【重征算法路】之七:最大子段和算法 (动态规划)

又是18天没看算法了,最近一直忙着给别人做网站。赶紧把自己拉回来看算法、写博客!

算法介绍

问题:
给定n个整数(可能为负数)组成的序列a1——an,求该序列如 ai+……+aj 的子段和的最大值。当所给的整数均为负数时定义子段和为0。

依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。

例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-20,11,-4,13,-5,-2)时,最大子段和为20。

最大子段和是动态规划中的一种。

算法时间复杂度

两种算法,算法1的时间复杂度为O(n^2)。
算法2的时间复杂度为O(n)。

算法1代码·C++版

int MaxSum(int n,int a[],int besti,int bestj){
  int sum=0;
  for(int i=1;i<=n;i++){
  	int thissum=0;
  	for(int j=i;j<=n;j++){
  		thissum+=a[j];
  		if(thissum>sum){
  			sum=thissum;
  			besti=i;
  			bestj=j;
  		}
  	}
  }
  return sum;
}

算法2代码·C++版

int MaxSum(int n,int a[10]){
  int sum=0,b=0;
  for(int i=0;i<=n;i++){
  	if(b>0) b+=a[i];
  	else b=a[i];
  	if(b>sum) sum=b;
  }
  return sum;
}

算法解释

API解释:

该算法1的API为:MaxSum(n,a[],besti,bestj)
n是a数组的长度
a是一维数组
besti、bestj用来返回最大子段的下标
该算法的返回值为最大子段的和
该算法2的API为:MaxSum(n,a[])
n是a数组的长度
a是一维数组
该算法的返回值为最大子段的和

运行解释:
算法1采用的是暴力方法,两个for循环。第一个for循环遍历,作为子段的起始下标;第二个for循环遍历,作为子段的末位下标。然后每次子段相加与sum相比,最后输出sum。

算法2采用的是动态规划思想。从该算法的代码运行角度上来解释:
b先从a[0]处开始累加计数,只要累加是负数b就为0,不赋值给sum,当等于正数时,赋值给sum,开始存入sum。之后b再继续累加,如果b加上之后的数大于sum就赋值给sum,不大于就让b一直加着吧,直到结束。

扫描二维码关注公众号,回复: 8923854 查看本文章

总结一下就是,算法1需要穷举出所有的子段和且比较大小,而算法2在动态规划的思想上,采用公式推导,求出了算出最大字段和的最简公式并用算法2实现。换句话说,算法2变成了数学问题。

算法时间测试

测试数据:a[10]={-2,11,-4,13,-5,-2}
算法1平均时间:0.26us
算法2平均时间:0.16us

测试数据:a[32]={-2,11,-4,13,-5,-2,35,-9,-22,10,9,-2,-19,20,1,2,-8,1,-3,-8,22,-10,6,5,4,-7,-8,-1,-2,16}
算法1平均时间:0.3us
算法2平均时间:0.17us

发布了57 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43592352/article/details/101538020