最大子数组和问题
(一)最大字数组和问题
问题:给定n个整数(可能为负数)组成的序列a[1],a[2]…a[n],求该序列a[i],a[i+1]…a[j]的子段和的最大值。当所给整数均为负数的时候,定义子段和为0.《百度百科》
- 分析
显然问题可以在O(n2)的时间复杂度上解决,但是考虑到当n很大(比如1e9)时,O(n2)的时间复杂度并不能完美的解决这个问题。因此我们是否可以对O(n2)的代码进行优化呢?答案是肯定的。
不妨设,a[i],a[i+1]...a[j]已经是所求最大子数组和的部分前缀并且已知和为sum且当前最大子数组和为maxx,继续考虑a[j+1]的情况,如果sum加上a[j+1]可以使和sum大于a[j+1],则更新sum的值为sum + a[i]反之更新sum的值为a[i]。由此我们可以得到递推公式
sum = max(sum + a[i], a[i])
当sum的值大于已知最大字数组和maxx的时候更新maxx即可。
- Python代码
import math
def fun(arr):
n = len(arr)
if n <= 0:
return 0
sum = 0
maxx = 0
for i in range(0, n):
sum = max(sum + arr[i], arr[i])
if sum >= maxx:
maxx = sum
return maxx
- 流程图
- 单元测试
接下来我们使用单元测试来测试一下代码,一下是单元测试代码:
import my_math, unittest
arr0 = []
arr1 = [-1, -2, -3, -4]
arr2 = [-2, 11, -4, 13, -2, -5]
class ProductTestCase(unittest.TestCase):
def test0(self):
p = my_math.fun(arr0)
self.assertEqual(0, p, 'Worng Answer!')
def test1(self):
p = my_math.fun(arr1)
self.assertEqual(0, p, 'Worng Answer!')
def test2(self):
p = my_math.fun(arr2)
self.assertEqual(20, p, 'Worng Answer!')
if __name__=='__main__': unittest.main()
本测试代码实现了条件覆盖,样例数组arr0为空测试数组长度小于等于0的情况(实际小于0的情况不存在),arr1数组测试数组值全为负数时返回最大子数组和为0,arr2数组可以测试sum>=maxx的两个条件。测试代码结果如下: