问题描述:给一个数组a1,a2,...,an.求这个数组的最大连续子段和。(非空子段)
即,定义Sij=ai+...+aj,则题目要求的是 max{Sij}(1<=i<=j<=n)
N^3枚举和优化之后的N^2枚举就不说了,还有NlogN的二分算法也不提,想了解的可以看我的另一篇博客:http://www.cnblogs.com/itlqs/p/5097504.html
这里主要详解两种O(n)的算法。
方法一:动态规划
dp[i]表示以第i位为结尾的最大子段和。那么转移方程就是:dp[1]=a[1],dp[i]=max{dp[i-1]+a[i],a[i]} (i>=2)
以第i位为结尾的最大子段和,要么是它接上了前一个的最大子段和,要么就是它自己。
最后的结果就是扫一遍dp[1..n]的最大值。
方法二:前缀和
前缀和Sn=a1+...+an可以预处理出来。(S0=0)
则Sij=ai+...+aj=Sj-Si-1
题目要求的实际上就是max{Sij}=max{Sj-Si-1}=max{Sj-min{Si-1}}(1<=i<=j<=n)
那么也就是说,对于每一个Sj,我们都要找它前面的最小的一个前缀和减掉,那么这个min{Si-1}是可以动态维护的,所以O(n)扫一遍结果就出来了。