剑指Offer 42. 连续子数组的最大和(Easy)/ 918. 环形子数组的最大和(Medium)

这篇博客探讨了如何使用动态规划算法求解连续子数组的最大和问题,提供了三种不同的实现方式:动态规划(64ms)、双循环辅助变量(72ms)和数组原地变换(76ms)。每种方法都通过迭代更新数组元素来找到最大子数组和,并给出了详细的代码解释。此外,还介绍了如何扩展该问题到环形子数组的最大和问题,考虑无环和有环两种情况,确保找到最大和。
摘要由CSDN通过智能技术生成

在这里插入图片描述
【题目链接】

题解

  1. 连续子数组的最大和(动态规划,清晰图解)

思路

在这里插入图片描述
在这里插入图片描述

代码

class Solution:
    ### 1124 动态规划(64 ms,19.7 MB)
    def maxSubArray(self, nums: List[int]) -> int:
        dp = [0] * len(nums) # dp[i] 表示以元素 nums[i] 为结尾的连续子数组最大和
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            dp[i] = max(dp[i-1]+nums[i], nums[i]) # 前一个子数组总和dp[i-1]+当前元素nums[i] 与 当前元素nums[i] 谁更大
        
        return max(dp) # 返回数组中的最大值

    ### 1124 双循环辅助变量(72 ms,17.1 MB)
    def maxSubArray(self, nums: List[int]) -> int:
        pre, res = 0, nums[0]   # 定义第一个循环变量pre,保存最大值的变量res
        for cur in nums:        # 定义第二个循环变量cur
            cur += max(pre, 0)  # 若从头到pre的子数组的总和pre > 0 则加上cur,否则只取cur(当前这个nums[i]的正负性未知)(max取0表示直接去掉之前为负贡献的子数组)
            pre = cur           # pre所代表的子数组长度加一,则加上cur更新
            res = max(res, cur) # 若cur为正,则res增大且更新

        return res

    ### 1124 数组原地变换(76 ms,17.9 MB)
    def maxSubArray(self, nums: List[int]) -> int:
        for i in range(1, len(nums)):
            # nums[i] = 从头到pre的子数组的总和nums[i-1] + nums[i](但当前这个nums[i]的正负性未知)(max取0表示直接去掉之前为负贡献的子数组)
            nums[i] += max(nums[i-1], 0)

        return max(nums) # 返回数组中的最大值
  • 返回和最大的连续子数组
def maxSubArray(nums) -> int:
    pre, res = 0, nums[0]   # 定义第一个循环变量pre,保存最大值的变量res
    start = end = 0
    tmp = 0
    for i, cur in enumerate(nums):        # 定义第二个循环变量cur
        if pre < 0:
            tmp = 0
            start = i
        else:
            tmp = pre
            
        cur += tmp  # 若从头到pre的子数组的总和pre > 0 则加上cur,否则只取cur(当前这个nums[i]的正负性未知)(max取0表示直接去掉之前为负贡献的子数组)
        pre = cur           # pre所代表的子数组长度加一,则加上cur更新
        if res < cur:
            res = cur
            end = i
#     print(start, end)
    return res, nums[start: end+1] if start <= end else [nums[start]]

918. 环形子数组的最大和

在这里插入图片描述

class Solution:
    def maxSubarraySumCircular(self, nums: List[int]) -> int:
        n = len(nums)   

        # 考虑无环情况:最大和子数组不包含首尾元素,只需考虑中间为最大即可
        max_ = float('-inf')
        pre = 0
        for i in range(n):
            pre = max(0, pre) + nums[i]
            max_ = max(max_, pre)
        # 如果最子数组和小于0,说明数组中全为负数,返回最大负数即可
        if max_ < 0:
            return max_

        # 考虑有环情况:最大和子数组包含首尾元素,只需考虑中间为最小即可(即两边最大)
        pre = 0
        min_ = float('inf')
        for i in range(n):
            pre = min(0, pre) + nums[i]
            min_ = min(min_, pre)
        
        # 比较有环、无环哪种情况的子数组和更大
        # 有环状态下,要使得两端之和最大,必须让中间的子数组最小,即最后有环情况下的最大子数组和为sum(nums)-min_
        return max(max_, sum(nums) - min_)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值