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

题目链接:点击这里

1.动态规划

思路:令状态 dp[i] 表示以 A[i] 作为末尾的连续序列的最大和(即 A[i] 必须作为连续序列的末尾)

通过这个 dp[\ ] 数组,要求的最大子序和其实就是 dp[0],dp[1],…,dp[n-1] 中的最大值 。

现作如下考虑:因为 dp[i] 要求是必须以 A[i] 结尾的连续序列,那么只有两种情况:

  1. 这个最大和的连续序列只有一个元素,即以 A[i] 开始,以 A[i] 结尾。
  2. 这个最大和的连续序列有多个元素,即从前面某处 A[p] 开始 (p<i),一直到 A[i] 结尾。

对第1种情况,最大和就是 A[i] 本身。

对第2种情况,最大和是 dp[i-1] + A[i],即 A[p]+...+A[i-1] + A[i] = dp[i-1] + A[i]

于是得到状态转移方程:dp[i] = max\left\{A[i], \ dp[i-1]+A[i]\right\},其中 dp[0] = A[0]

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        dp = [0] * n

        dp[0] = nums[0]
        for i in range(1, n):
            dp[i] = max(nums[i], dp[i - 1] + nums[i])
        
        return max(dp)

空间优化:

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

2.分治

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        return self.calc(nums, 0, n - 1)
    
    def calc(self, nums:List[int], l:int, r:int) -> int:
        if l == r:
            return nums[l]
        
        mid = (l + r) // 2
        
        left = self.calc(nums, l, mid)
        right = self.calc(nums, mid + 1, r)
        
        lmax, lsum = nums[mid], 0
        for i in range(mid, l - 1, -1):
            lsum += nums[i]
            lmax = max(lmax, lsum)
        
        rmax, rsum = nums[mid + 1], 0
        for i in range(mid + 1, r + 1):
            rsum += nums[i]
            rmax = max(rmax, rsum)
        
        return max(left, right, lmax + rmax)
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        return Solution.calc(self, nums, 0, n - 1)
    
    def calc(self, nums:List[int], l:int, r:int) -> int:
        if l == r:
            return nums[l]
        
        mid = (l + r) // 2
        
        left = Solution.calc(self, nums, l, mid)
        right = Solution.calc(self, nums, mid + 1, r)
        
        lmax, lsum = nums[mid], 0
        for i in range(mid, l - 1, -1):
            lsum += nums[i]
            lmax = max(lmax, lsum)
        
        rmax, rsum = nums[mid + 1], 0
        for i in range(mid + 1, r + 1):
            rsum += nums[i]
            rmax = max(rmax, rsum)
        
        return max(left, right, lmax + rmax)

Python类中方法相互调用的两种方式:

  1. 类名.方法名(self)
    注意:方法名内必须传入一个实例对象的指针,self后可根据方法定义放入适当实参

  2. self.方法名(方法列表)
    方法列表不应该包括self

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容