本题有三种作法,各位须要根据每一个题的数据范围来决定本身用哪一种方法。spa
本题解中统一设最大和为Max。code
咱们能够枚举它的子序列,也就是枚举它的长度、起点和终点。咱们不妨设长度为i,起点为j,终点为k,当前子序列的和为s。因而咱们就有了下列核心代码:blog
Max=a[1];//最大和初始化为第一个数 for(i=1;i<=n;i++)//枚举长度 for(j=i;j<=n;j++){//枚举起点 s=0;//当前序列和初始化为0 for(k=i;k<=j;k++)//枚举终点 s+=a[k];//计算和 if(s>Max)Max=s;//比较 } printf("%d",Max);//输出
这种方法在时限1s的题目中只能经过n<=450的范围。class
可是本题的序列长度n<=200000。方法
因此采用该方法超时。总结
咱们能够先求出从第一个数到当前数的和,而后枚举起点和终点,计算每个子序列的和。因而咱们就有了下列核心代码:数据
memset(s,0,sizeof(s));//初始化前缀和 for(i=1;i<=n;i++)s[i]=s[i-1]+a[i];//计算前缀和 Max=a[i];//初始化最大值为第一个数 for(i=1;i<=n;i++) for(j=i;j<=n;j++) Max=max(Max,s[j]-s[i-1]);//枚举起点和终点。 //注意是i-1!由于计算从第i个数开始的和须要减去前i-1个数的和 printf("%d",Max);
怎么有点像DP?di
这种方法在时限1s的题目中只能勉强经过n<=10000的范围。时间
可是本题的序列长度n<=200000。co
因此采用该方法也超时。
不妨设s为以第i个数结尾的最大和,并每次计算和。
若当前和比最大值大,就更新最大值。
若当前和比0小,就把和清0。
核心代码:
scanf("%d",&n); s=0; Max=-2e9; for(i=1;i<=n;i++){ scanf("%d",&a); s+=a; if(s>Max)Max=s; if(s<0)s=0; } printf("%d",Max);
这种方法在时限1s的题目中能勉强经过n<=100000000的范围。
因为本题的序列长度n<=200000。
因此能够采用这种方法。
总结:必定要明白第三种方法的道理,而且能本身编写代码,这样水平才能有所提高。