剑指 Offer 42. 连续子数组的最大和

112 阅读2分钟

前言:剑指offer刷题系列

问题:

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

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

示例:

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

思路:

看到这个题目思考了一下,就有了如下思路:

  • first,定义一个变量 maxnum,用来记录全局的最大子数组和,初始化为数组的第一个元素 nums[0]。
  • second,遍历数组中的每个元素 nums[i],从第二个元素开始,用一个变量 last_num 记录前一个元素 nums[i-1] 的值。
  • then,判断 last_num 是否大于 0,如果是,说明它对当前元素 nums[i] 有增益效果,可以将它们相加得到更大的子数组和,并更新 nums[i] 的值;如果不是,说明它对当前元素 nums[i] 没有增益效果,可以直接舍弃它,保持 nums[i] 的值不变。
  • last,比较 maxnum 和 nums[i] 的大小,取较大者作为新的 maxnum,并继续遍历下一个元素。

遍历完整个数组后,maxnum 就是最大子数组和,返回它即可。

基于上述思考,代码如下:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        maxnum = nums[0]
        for i in range(1,len(nums)):
            last_num = nums[i-1]
            if last_num > 0:
                nums[i] += last_num
            maxnum = max(maxnum,last_num)
        return maxnum

执行结果如下图:

image-20230901204725324.png

学到的知识点:

动态规划类型的题目,对我来说还是优点难的,但是这类题目一般是将一个较难的题目,分解为较简单的子问题。 一般首先按照问题的时间或空间特征,把问题分为若干个阶段。在每个阶段都需要作出决策,从而影响下一个阶段的状态。然后就是确定状态:用一个或多个变量来描述每个阶段的状态,即问题在该阶段所处的情况。状态一般是历史决策的结果,也是未来决策的依据。然后,根据不同的状态,考虑在当前阶段可以做出什么决策,以及做出这个决策后会产生什么后果,从而确定下一个阶段的状态。通过递推或者逆推的方式,找出每个状态下的最优策略,即能够使得整个问题达到最优解的决策。最后构造最优解:根据每个状态下的最优策略,从初始状态开始,逐步执行决策,直到结束状态,得到最优解。