LeetCode: 54 (动态规划)
问题描述:
给定由 n 个整数组成的序列 a1 , a2, …… , an ,求该序列字段和的最大值,当所以整数均为负值时定义其最大字段和为 0。数学描述为:
MAX_SUBSTRING= MAX{0 ,max1<=i<=j<=nk=ija[k]}
例子:给定{-2,11,-4,13,-5,-2},
最大字段和为 11+(-4)+13 = 20
常规做法如下:
def common_method(array):
length = len(array)
sum_max = 0 # 记录最大子序列的总和
begin_index = 0 # 记录 最大子序列的 起点
end_index = 0 # 记录 最大子序列的 终点
for i in range(length): # 从 i 开始
for j in range(i ,length):# 从 j 结束 的子序列
sum_sub = 0 # 记录 i 到 j 子序列的总和
for k in range(i , j + 1): # 为了计算 从 i 开始 到 j 结束的子序列总和
sum_sub += array[k]
if sum_max < sum_sub: # 与 当前最大值进行对比
sum_max = sum_sub
begin_index = i
end_index = j
print(begin_index , " <-----> " , end_index)
print(sum_max)
对暴力解法进行修改:
def common_method_change(array):
length = len(array)
max_sum = 0
begin_index = 0
end_index = 0
for i in range(length):
sum_sub = 0
for j in range(i , length):
sum_sub += array[j]
if sum_sub > max_sum:
max_sum = sum_sub
begin_index = i
end_index = j
print(begin_index , " <-----> " , end_index)
print(max_sum)
分治法分析:
def divide_conquer_method(array , left , right):
sum = 0
if left == right:
if array[left] > 0:sum = array[left]
else:sum = 0
else:
center = (left + right) // 2
left_sum = divide_conquer_method(array , left , center) # 左子问题
right_sum = divide_conquer_method(array , center + 1 , right) # 右子问题
# 第三个情况的开始
s1 , lefts ,i = 0 , 0 ,center
while i >= left: # 从中间往当前 left 方向找最大,而且是从 center 开始的最大
lefts += array[i]
if lefts > s1:s1 = lefts
i -= 1
s2 ,rights ,i= 0 , 0 , center + 1
while i <= right: # 从中间往当前 right 方向找最大,而且是从 center 开始的最大
rights += array[i]
if rights > s2:s2 = rights
i += 1
sum = s1 + s2
if sum < left_sum:sum = left_sum
if sum < right_sum:sum = right_sum
return sum
动态规划分析:( O(N) )
def dynastic_method(array):
length = len(array)
sum_sub = 0
b = 0
for j in range(length):
if b > 0:
b = b + array[j]
else:
b = array[j]
if b > sum_sub:
sum_sub = b
return sum_sub
#利用规律求解,O(N)
def maxSubArray(nums):
for i in range(1 , len(nums)):
if nums[i - 1] > 0:
nums[i] = nums[i] + nums[i - 1]
print(nums)
return max(nums)