【动态规划】连续子数组的最大和
题目
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如,输入数组为[1, -2, 3, 10, -4, 7, 2, -5], 最大和的子数组为[3, 10, -4, 7, 2],因此输出该子数组的和18。
解答
1,动态规划,Time: O(N), Space: O(1)
动态规划, f(i)表示以第i个数字结尾的子数组的最大和, 题目求max(f(i))
f(i) = nums[i] i=0 or f(i-1)≤0
f(i) = f(i-1) + nums[i] i>0 and f(i-1)>0
2,遍历一遍,记录最大和,Time: O(N), Space: O(1)
3,滑动窗口枚举一遍也可以,窗口大小[1, len(n)+1],时间复杂度较高,O(n^2)
这两种方法一样,代码也差不多,第二种方法按自己思路实现的;动态规划更优雅。另外,每种方法都应该合理地处理无效的输入:空、全负数、全0、全正数
代码实现:
# class Solution:
# # 遍历一遍,记录最大和
# def FindGreatestSumOfSubArray(self, nums):
# if not nums:
# return 0
#
# max = 0
# ans = -1 # 存最大和,末尾表示当前的最大和
# spe = float('-inf')
#
# for index, x in enumerate(nums):
# if x + max > 0:
# if x + max > ans: # 比当前出现过的最大和还要大
# ans = max + x
# max = max + x
# else: # 遇到当前x, 相加之和<0,抛弃x之前的元素(包含x)
# max = 0
#
# if x > spe: # nums全部 ≤ 0 的情况,找到最大值即可
# spe = x
#
# if ans == -1: # nums全部 ≤ 0 的情况
# return spe
# return ans
class Solution:
# 动态规划
def FindGreatestSumOfSubArray(self, nums):
if not nums:
return 0
cur = 0 # f(i)加下一个数以后
max = float('-inf') # 到第i位的最大和
dp = []
for x in nums:
if cur <= 0: # x之前的元素之和对之后的计算不能起到增益作用,抛弃 例:[1, -2, 3, 10, -4, 7, 2, -5], x=3时, 应抛弃[1, -2]
cur = x
else:
cur += x
if cur > max:
max = cur
dp.append(max) # f(i)
print(dp) # 记录了每位最大和
return max
s = Solution()
# ans = s.FindGreatestSumOfSubArray([-4, -2, -3, -11])
ans = s.FindGreatestSumOfSubArray([1, -2, 3, 10, -4, 7, 2, -5]) # dp: [1, 1, 3, 13, 13, 16, 18, 18]
# ans = s.FindGreatestSumOfSubArray([6, -3, -2, 7, -15, 1, 2, 2])
print(ans)