【Leetcode | Python】53. 最大子数组和 [动态规划]

本文介绍了如何使用动态规划解决最大连续子数组和问题,通过转化为以元素i结尾的最大子数组和的子问题,利用dp列表来存储中间结果。更新后的版本指出,实际上只需要dp列表的最后一个元素,简化了实现。
摘要由CSDN通过智能技术生成

🚀总结

本题的核心在于维护一个列表 dp,列表中第 i 个元素表示以数组中第 i 个元素结尾的最大子数组和。

以数组中第 i 个元素结尾的最大子数组和,要么是元素 i 自身(前面的最大子数组和小于0),要么是元素 i-1 加上前面的最大子数组和(前面的最大子数组和大于0)

对于数组中第 i 个元素:

  • 如果以数组中第 i-1 个元素结尾的最大子数组和大于0,则加上以前一个数字结尾的最大子数组和,使得当前数字结尾的最大子数组和更大,即
    以数组中第 i 个元素结尾的最大子数组和 = 以数组中第 i-1 个元素结尾的最大子数组和 + 数组中第 i 个元素。
  • 如果以数组中第 i-1 个元素结尾的最大子数组和小于0,则没有必要加上以前一个数字结尾的最大子数组和,“另起炉灶”, 即
    以数组中第 i 个元素结尾的最大子数组和 = 数组中第 i 个元素。

公式表示如下:
d p [ i ] = { d p [ i − 1 ] + n u m s [ i ] , if  d p [ i − 1 ] > 0 n u m s [ i ] , if  d p [ i − 1 ] ≤ 0 dp[i] = \begin{cases} dp[i - 1] + nums[i], & \text{if } dp[i - 1] > 0 \\ nums[i], & \text{if } dp[i - 1] \leq 0 \end{cases} dp[i]={dp[i1]+nums[i],nums[i],if dp[i1]>0if dp[i1]0

📇题目在这里插入图片描述

⭐思路

对于一个整数数组 nums,它所能构成的连续子数组非常多,直接遍历所有可能的连续子数组非常困难。因此需要将这个问题转化为很多个子问题,并且确保:① 解决所有的子问题能够确保解决原问题;② 子问题的求解之间存在联系,从而提高计算效率

“最大连续子数组和” 的问题转化为 “以元素 i 结尾的最大连续子数组和” 的子问题,经过这种转化:
① 如果以 i ⋆ \text{i}^\star i 结尾的最大连续子数组和是所有以 i(i = 1, 2, …, n) 结尾的最大连续子数组和中最大的那一个,那么以 i ⋆ \text{i}^\star i 结尾的最大连续子数组和也是这个整数数组的最大子数组和;
② 以 i 结尾的最大连续子数组和与以 i-1 结尾的最大连续子数组和之间存在联系。

🛠️代码

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = []
        dp.append(nums[0])  # dp 列表的第一个元素为数组第一个元素
        for i in range(1, len(nums)):
            if dp[i - 1] > 0:  # 如果以前一个元素结尾的最大子数组和大于0
                dp.append(nums[i] + dp[i - 1])  # 以当前元素结尾的最大子数组和 = 以前一个元素结尾的最大子数组和 + 当前元素
            else:  # 如果以前一个元素的最大子数组和小于等于0
                dp.append(nums[i])  # 以当前元素结尾的最大子数组和 = 当前元素
        return max(dp)

分割线(2024/03/29更新)

回顾之前的代码,发现 dp 列表实际上并不是必要的,因为整个过程中其实只需要 dp 列表的最后一个元素,只需要用一个变量 previous_max 代替就可以。代码如下:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        previous_max = nums[0]
        res = previous_max
        for i in range(1, len(nums)):
            if previous_max > 0:  # 如果以前一个元素结尾的最大子数组和大于0
                previous_max = nums[i] + previous_max  # 以当前元素结尾的最大子数组和 = 以前一个元素结尾的最大子数组和 + 当前元素
            else:  # 如果以前一个元素的最大子数组和小于等于0
                previous_max = nums[i]  # 以当前元素结尾的最大子数组和 = 当前元素
            if previous_max > res:  # 更新结果
                res = previous_max
        return res
  • 54
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值