首先,题目要求求出连续子序列的和的值为最大的子序列,有点绕口,多读几遍就清楚了。一个序列有大量的连续子序列(排列组合问题了),要从众多子序列中挑出和的值为最大的那个序列。暴力解决的思路很简单,直接遍历所有的连续子序列并求它们的和,分别对比和的大小,取最大的值即可,时间复杂度为n^2。
但是,算法之所以简单,在于它的高效性。换个思路:我们其实并不需要求出每个连续子序列的和。有一个既定事实,那就是每一个连续子序列(以下简称子序列)都对应着一个 序列结尾位置,不同的子序列对应着一个 序列结尾位置。例如:
- 序列结尾位置的定义
有序列 {1, 3, -2, 4, -5},每一个逗号代表一个序列结尾位置,子序列{1,3,-2};{3,-2};{-2}均对应同一个结尾位置(第三个逗号),那么以该位置结尾的子序列中,最大值显然为2。
- 问题转化
原始序列中,一共有n-1个序列结尾位置,我们只需分别求出以n-1个位置结尾的最大子序列的值,再从n-1个最大子序列的值中求出最大值即为原始序列的最大连续子序列和。
- 核心思想
回到例题,以第三个逗号结尾的最大子序列和怎么求?当前处理到第i个数,即为-2。有两种情况,当前i-1个数的和sum大于0时,那么前i个数的最大连续子序列和为sum+a[i];当前i-1个数的和小于0时,前i个数的和为a[i]。这就转化成了0-1揹包的动态规划问题。求前i+1个数的最大连续子序列和为:
当sum+a[i]>0时:
sum+a[i]+a[i+1]
当sum+a[i]<0时:
a[i+1]
如此递推状态转换方程就可以建立了。