最大连续子数组和(最大子段和)
- 问题描述
给定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
例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。-- 引用自《百度百科》
问题分析
- 采用动态规划的方法
- 设sum[i]为以第i个元素结尾且和最大的连续子数组。假设对于元素i,所有以它前面的元素结尾的子数组的长度都已经求得,那么以第i个元素结尾且和最大的连续子数组实际上,要么是以第i-1个元素结尾且和最大的连续子数组sum[i-1]加上这个元素a[i],要么是只包含第i个元素a[i]。
即递推公式为:sum[i]=max(sum[i−1]+a[i],a[i]) - 通过判断sum[i-1] + a[i]是否大于a[i]来做选择,而这实际上等价于判断sum[i-1]是否大于0。
由于每次运算只需要前一次的结果,因此并不需要像普通的动态规划那样保留之前所有的计算结果,只需要保留上一次的即可,因此算法的时间和空间复杂度都很小。
算法思路参考自
codingnet地址源代码
def maxsum(arr):
max=0
sum=arr.copy()
if len(arr)==0:
return 0
else:
for i in range(1,len(arr)):
if sum[i-1]>0:
sum[i]=sum[i-1]+arr[i]
else:
sum[i]=arr[i]
if sum[i]>max:
max=sum[i]
return max
源代码流程图
测试代码
选择条件组合覆盖:
共有6个条件
1.len(arr)=0
2.len(arr)>0
3.sum[i-1]>0
4.sum[i-1]<=0
5.sum[i]>max
6.sum[i]<=max
则条件组合判断为:
- len(arr)=0
- len(arr)>0,sum[i-1]>0,sum[i]>max
- len(arr)>0,sum[i-1]>0,sum[i]<=max
- len(arr)>0,sum[i-1]<=0,sum[i]>max
- len(arr)>0,sum[i-1]<=0,sum[i]<=max
设计的测试用例分别为以下所示: - arr0=[]
- arr1=[-1,-2,-3,-4,-5,-6]
- arr2=[1,2,3,4,5,6] #21
- arr3=[-1,-2,-3,-4,-5,20]#20
arr4=[1,2,3,4,5,-20,6,-30]#15
测试程序代码
import unittest
from maxsum import *
arr0=[]
arr1=[-1,-2,-3,-4,-5,-6]
arr2=[1,2,3,4,5,6] #21
arr3=[-1,-2,-3,-4,-5,20]#20
arr4=[1,2,3,4,5,-20,6,-30]#15
class TestMaxsum(unittest.TestCase):
#test for maxsum
def test0(self):
self.assertEqual(0,maxsum(arr0))
def test1(self):
self.assertEqual(0,maxsum(arr1))
def test2(self):
self.assertEqual(21,maxsum(arr2))
def test3(self):
self.assertEqual(20,maxsum(arr3))
def test4(self):
self.assertEqual(15,maxsum(arr4))
if __name__=='__main__':
print()
unittest.main()
程序测试结果截图
[程序测试截图][]
---恢复内容结束---
总结
要多加练习python语言以及markdown语法的使用