对于求解连续最大子序列和问题,有4种解决方法,暴力算法、分治,动态规划,还有一个记不到名字的方法,在这个博客里,我们讲一下用动态规划求解。
要解决的问题:对于一个数列,找到这个数列的一个连续的子数列,使得这个子数列的和最大。
**方法:**对于子数列的每一个元素 L[i],我们求解从第一个元素L[0]开始到 L[i] 的最大子数列和,并且存储在 ms 中。
对于 L[i], 有两种处理方法,一种是把 L[i] 作为最大子序列的开始,一种是把它接连在前面的最大子序列的后面,转移方程为
ms[i]=max(ms[i-1]+L[i], L[i])
为了在代码中输出最大子序列,我们用 flag 列表标记子序列的开头,如果 L[i] 是候选最大子序列的开头,则 flag[i]=1,否则 flag[i]=0。最后输出的时候我们找到max(ms),index(max(ms))为最大子序列和的末端,继续向前寻找即可。
python代码:
def maximum_subarray_problem(arr):
length = len(arr)
ms = [0] * length
ms[0] = arr[0]
# flag为1的时候表示是子序列的开头,若要把这个子序列数出来,
# 只要标记对于每个元素而言,从第一个元素到它的最大子序列,它是不是开头即可
flag = [1] * length
maximum_sub = []
for i in range(1, length):
if (ms[i - 1] + arr[i]) > arr[i]:
ms[i] = ms[i - 1] + arr[i]
flag[i] = 0
else:
ms[i] = arr[i]
max_value = max(ms)
max_index = ms.index(max_value)
for i in range(max_index, -1, -1):
if flag[i] == 1:
maximum_sub.insert(0, arr[i])
break
maximum_sub.insert(0, arr[i])
return max_value, maximum_sub
if __name__ == '__main__':
l = [12, 5, -1, 31, -61, 59, 26, -53, 58, 97, -93, -23, 84, -15, 6]
dp, sub = maximum_subarray_problem(l)
print(dp, sub)
测试结果
187 [59, 26, -53, 58, 97]