最大子数组和

发布于:2023-09-16 ⋅ 阅读:(62) ⋅ 点赞:(0)

53. 最大子数组和

给出了三种解决方案的代码实现,分别是:滑动窗口(1、2)、动态规划(3、4)以及前缀和(5)


class MaxSubArray:
    """
    53. 最大子数组和
    https://leetcode.cn/problems/maximum-subarray/description/
    """
    def solution(self, nums: List[int]) -> int:
        res = float('-inf')
        sum = 0
        for num in nums:
            sum += num
            res = max(res, sum)
            # 这样保证了最大子数组和必然是以正数开头的
            if sum < 0:
                sum = 0
        return res

    def solution2(self, nums: List[int]) -> int:
        """
        滑动窗口
        :param nums:
        :return:
        """
        left, right = 0, 0
        window_sum = 0
        res = float('-inf')
        while right < len(nums):
            # 扩大窗口并更新窗口内的元素和
            window_sum += nums[right]
            right += 1
            # 更新答案
            res = max(res, window_sum)

            # 判断窗口是否要收缩
            while window_sum < 0:
                window_sum -= nums[left]
                left += 1

        return res

    def solution3(self, nums: List[int]) -> int:
        """
        动态规划
        时间复杂度:O(n)
        空间复杂度:O(n)
        :param nums:
        :return:
        """
        n = len(nums)
        # dp[i] 记录以nums[i]为结尾的 最大子数组和
        dp = [0] * n
        # base case
        dp[0] = nums[0]
        # 状态转移方程,要么自成一派,要么和前面的数组合并
        for i in range(1, n):
            dp[i] = max(dp[i-1]+nums[i], nums[i])

        res = float('-inf')
        for i in range(n):
            res = max(res, dp[i])

        return res

    def solution4(self, nums: List[int]) -> int:
        """
        动态规划改进,可以看出来dp[i] 只和dp[i-1]的状态有关,可进一步压缩空间
        时间复杂度:O(n)
        空间复杂度:O(n)
        :param nums:
        :return:
        """
        n = len(nums)
        res = float('-inf')
        # base case
        dp_0 = nums[0]
        # 状态转移方程,要么自成一派,要么和前面的数组合并
        for i in range(1, n):
            dp_1 = max(dp_0 + nums[i], nums[i])
            dp_0 = dp_1

            # 顺便更新结果
            res = max(res, dp_1)

        return res

    def solution5(self, nums: List[int]) -> int:
        """
        前缀和
        pre_sum[i]表示nums[0...i-1]的累加和
        :param nums:
        :return:
        """
        n = len(nums)
        pre_sum = [0] * (n+1)
        for i in range(1, n+1):
            pre_sum[i] = pre_sum[i-1] + nums[i-1]

        res = float('-inf')
        min_val = float('inf')
        for i in range(n):
            # 维护 minVal 是 preSum[0..i] 的最⼩值
            min_val = min(min_val, pre_sum[i])
            # 以 nums[i] 结尾的最⼤⼦数组和就是 preSum[i+1] - min(preSum[0..i])
            res = max(res, pre_sum[i+1]-min_val)

        return res


本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到