【动态规划】连续子数组的最大和

题目

输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为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)
posted @ 2020-01-03 11:34  961897  阅读(390)  评论(0编辑  收藏  举报