剑指offer 42 -连续子数组的最大和 - python

112 阅读1分钟

题目描述:

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。

示例1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6

提示:

1 <= arr.length <= 10^5
-100 <= arr[i] <= 100


最大和连续子数组一定有如下几个特点:

  • 第一个不为负数
  • 如果前面数的累加值加上当前数后的值会比当前数小,说明累计值对整体和是有害的;如果前面数的累加值加上当前数后的值比当前数大或者等于,则说明累计值对整体和是有益的。

解题步骤:

  • 定义两个变量,一个用来存储之前的累加值,一个用来存储当前的最大和。遍历数组中的每个元素,假设遍历到第 i i i个数时:

    • 如果前面的累加值为负数或者等于0,那对累加值清0重新累加,把当前的第 i i i个数的值赋给累加值。
    • 如果前面的累加值为整数,那么继续累加,即之前的累加值加上当前第 i i i个数的值作为新的累加值。
  • 判断累加值是否大于最大和:如果大于最大和,则更新最大和;否则,继续保留之前的最大和。


AC代码

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        sum = nums[0]
        presum = 0
        for i in nums:
            if presum < 0:
                presum = i
            else:
                presum += i
            sum = max(presum,sum)
        return sum

上面的解题思想可以归纳到动态规划的思路中,创建dp数组,其中 d p [ i dp[i dp[i]表示 n u m s [ i ] nums[i] nums[i]为结尾的连续子数组的最大和,并设置 d p [ 0 ] = n u m s [ 0 ] dp[0] = nums[0] dp[0]=nums[0]:

  • 如果nums[i] <=0,那么 d p [ i − 1 ] dp[i-1] dp[i−1]对 d p [ i ] dp[i] dp[i]没有贡献,设置 d p [ i ] = n u m s [ i ] dp[i] = nums[i] dp[i]=nums[i]
  • 否则, d p [ i ] = n u m s [ i ] + d p [ i − 1 ] dp[i] = nums[i] + dp[i - 1] dp[i]=nums[i]+dp[i−1]
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = [0 for i in range(len(nums))]
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            if dp[i - 1] > 0:
                dp[i] = dp[i -1] + nums[i]
            else:
                dp[i] = nums[i]

        return max(dp)