力扣(leetcode) 53. 最大子序和 (动态规划,非常清晰)

题目在这:https://leetcode-cn.com/problems/maximum-subarray/

思路分析:

一开始想用滑动窗口做这道题,后来一想,排序过后顺序不就乱套了,就没法找连续子数组了。

于是使用动态规划。
看了一个大佬的思路,很不错。

例如,示例 1 输入数组是 [-2,1,-3,4,-1,2,1,-5,4] ,我们可以求出以下子问题:

子问题 1:经过 -2−的连续子数组的最大和是多少;
子问题 2:经过 1 的连续子数组的最大和是多少;
子问题 3:经过 -3 的连续子数组的最大和是多少;
子问题 4:经过 4 的连续子数组的最大和是多少;
子问题 5:经过 -1 的连续子数组的最大和是多少;
子问题 6:经过 2 的连续子数组的最大和是多少;
子问题 7:经过 1的连续子数组的最大和是多少;
子问题 8:经过 -5 的连续子数组的最大和是多少;
子问题 9:经过 4 的连续子数组的最大和是多少。
一共 9 个子问题,这些子问题之间的联系并没有那么好看出来

例如「子问题 3」:经过 -3 的连续子数组的最大和是多少。

「经过 -3 的连续子数组」我们任意举出几个:

[-2,1,-3,4] ,-3是这个连续子数组的第 3 个元素;
[1,-3,4,-1] ,-3 是这个连续子数组的第 2 个元素;
……
我们不确定的是:-3−是连续子数组的第几个元素。那么我们就把 -3 定义成连续子数组的最后一个元素。在新的定义下,我们列出子问题如下:

子问题 1:以 -2 结尾的连续子数组的最大和是多少;
子问题 2:以 1 结尾的连续子数组的最大和是多少;
子问题 3:以 −3 结尾的连续子数组的最大和是多少;
子问题 4:以 4 结尾的连续子数组的最大和是多少;
子问题 5:以 -1结尾的连续子数组的最大和是多少;
子问题 6:以 2 结尾的连续子数组的最大和是多少;
子问题 7:以 1 结尾的连续子数组的最大和是多少;
子问题 8:以 -5 结尾的连续子数组的最大和是多少;
子问题 9:以 4 结尾的连续子数组的最大和是多少。
我们加上了「结尾的」,这些子问题之间就有了联系。我们单独看子问题 1 和子问题 2:

子问题 1:以 -2 结尾的连续子数组的最大和是多少;
以 -2 结尾的连续子数组是 [-2],因此最大和就是 −2。

子问题 2:以 1 结尾的连续子数组的最大和是多少;
以 1 结尾的连续子数组有 [-2,1] 和 [1] ,其中 [-2,1] 就是在「子问题 1」的后面加上 1 得到。-2 + 1 = -1 < 1−2+1=−1<1 ,因此「子问题 2」 的答案是 1。

大家发现了吗,如果编号为 i 的子问题的结果是负数或者 0 ,那么编号为 i + 1 的子问题就可以把编号为 i 的子问题的结果舍弃掉(这里 i 为整数,最小值为 1 ,最大值为 8),这是因为:

一个数 a 加上负数的结果比 a 更小;
一个数 a 加上 0 的结果不会比 a 更大;
而子问题的定义必须以一个数结尾,因此如果子问题 i 的结果是负数或者 0,那么子问题 i + 1 的答案就是以 nums[i] 结尾的那个数。

得到状态转移方程:

  • dp[i] = dp[i-1] + num[i] 当 dp[i-1] >0
  • dp[i] = num[i] 当 dp[i-1] <= 0

完整代码:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:

        length = len(nums)
        
        dp = length *[0]
        dp[0] = nums[0]

        for i in range(1,length):
            if dp[i-1] > 0:
                dp[i] = dp[i-1] +nums[i]
            else:
                dp[i] = nums[i]
        print(max(dp))
        return max(dp)

我们每次只需要得到 dp【i】 的最大值即可
所以进一步压缩状态:

完整代码:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:

            res = nums[0]

            a = nums[0]

            for i in range(1,len(nums)):
                if a > 0:
                    b = a + nums[i]
                    res = max(b,res)
                    a = b
                else:
                    a = nums[i]
                    res = max(a,res)
            print(res)
            return res**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值