问题:
给定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
例如,当(a1,a2,a3,a4,a4,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为20。
此问题最常见,也是最容易想到的办法:
对这种三层循环的解法进行初步的优化,因为数列和具有如下性质:
S[i] = S[i-1]+a[i];
再对上面的算法进行如下优化:
1.空间优化,由于没有必要把所有的子段和保存下来,因为直接用一个变量sum保存最大子段和便可
2.时间优化,由于S[i] = S[i-1]+a[i]因此不需要把所有的S求出来
代码如下:
以上已经是属于o(n^2)中最优的算法了,但对于1W+级的数据,处理速度仍然太慢。
于是思考以分治法:
1.把整个段分成两部分,m = (left+right)/2
2.最大子段和要么属于左边部分,要么属于右边部分,要么属于包含a[m],a[m+1]的某个中间部分
3.对于属于左右两部分的,可以递归求出,重点是处理中间部分。
4.由于中间部分必然包含a[m],a[m+1]。因此把a[m]~a[0]倒过来求和,最大者即为左边必然包括a[m]的最大子段和lmax,同理可得右边rmax,所以lmax+rmax必然是包含a[m],a[m+1]的最大子段和。
5.以上三者,返回其较大值
代码如下:
再思考这个问题,实际上是典型的子结构问题,可以使用动态规划来解。
定义b[i]为 子段结束位置为 i 时的最大子段和,那么当b[i-1]>0时,b[i] = b[i-1]+a[i]否则b[i] = a[i]
最后,数组b[i]中最大值必然为最大子段和 :