最大字段和

来源:互联网 发布:家庭矛盾 知乎 编辑:程序博客网 时间:2024/06/05 20:04

问题描述

给定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。


算法思想

算法一:穷举法

对序列中的所有子段进行遍历求和,通过比较不同子段的和,得到最大的子段和。

算法二:分治法

对于序列{a[i] | i = 1,2,3,…,n},取序列中心为分割点,将序列拆分为left:{a[i] | i = 1,2,…,n/2}和right:{a[i] | i = n/2+1,n/2+2,…,n}。这样最大的子序列将会有三种情况:(1)最大的子序列在left:{a[i] | i = 1,2,…,n/2}中;(2)最大的子序列在right:{a[i] | i = n/2+1,n/2+2,…,n}中;(3)最大的子序列一半在left,一半在right,也就是最大子序列中最少包含元素a[n/2]和a[n/2+1]。
对于这三种情况,只需要分别求解不同情况下的最大子段和,然后三者中最大的值既是整个序列的最大子段和。

算法三:动态规划

运用动态规划解决这个问题,关键的一步就是需要找到状态转移方程。对于序列{a[i] | i = 1,2,3,…,n},maxSum(m) = max{a[1]+a[2]+…+a[m]},即子字段{a[i] | i = 1,2,3,…,m}的最大字段和。由maxSum(m)到maxSum(m+1)的状态转移方程如下:
(1) 如果maxSum(m)>=0,maxSum(m+1)=maxSum(m)+a[m+1]
(2) 如果maxSum(m) < 0,maxSum(m+1)=a[m+1]
对于a[m+1]<0时,得到的maxSum(m+1) < maxSum(m)。所以,需要设置一个变量存储当前的最大字段值。上述的状态转移方程只是一个用于遍历不同子段值的方法。


代码实现

穷举法

# 算法的时间复杂度是O(n^3)max = 0for i = 1 to n :    for j = i to n :        sum = 0        for k = i to j :            sum += a[k]        if max < sum :            max = sum

分治法

# 算法的时间复杂度是O(nlogn)def maxSum(a[], left, right) :    max = 0    if left == right :        if left > 0 :            max = a[left]        else :            max = 0    else :        center = (left + right) / 2        leftMax = maxSum(a, left, center)        rightMax = maxSum(a, center+1, right)        centerSumLeft = 0        leftSum = 0;        for i = center to left :            leftSum += a[i]            if leftSum > centerSumLeft :                centerSumLeft = leftSum        centerSumRight = 0        rightSum = 0        for j = center+1 to right :            rightSum += a[j]            if rightSum > centerSumRight :                centerSumRight = rightSum        centerMax = centerSumLeft + centerSumRight        if leftMax > centerMax :            max = leftMax        else if centerMax > rightMax :            max = centerMax        else :            max = rightMax    return max

动态规划

# 算法的时间复杂度是O(n)max = 0sum = 0for i = 1 to n :    if sum >= 0 :        sum += a[i]    else :        sum = a[i]    if sum > max :        max = sum
0 0