【LeetCode 动态规划专项】最大子序和(53)

1. 题目

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

1.1 示例

  • 示例 1 1 1

  • 输入: nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

  • 输出: 6 6 6

  • 解释: 连续子数组 [4, -1, 2, 1] 的和最大,为 6 6 6

  • 示例 2 2 2

  • 输入: nums = [1]

  • 输出: 1 1 1

  • 示例 3 3 3

  • 输入: nums = [0]

  • 输出: 0 0 0

  • 示例 4 4 4

  • 输入: nums = [-1]

  • 输出: − 1 -1 1

  • 示例 5 5 5

  • 输入: nums = [-100000]

  • 输出: − 100000 -100000 100000

1.2 说明

1.3 提示

  • 1 ≤ n u m s . l e n g t h ≤ 3 ∗ 1 0 4 1 \le nums.length \le 3 * 10^4 1nums.length3104
  • − 1 0 5 ≤ n u m s [ i ] ≤ 1 0 5 -10^5 \le nums[i] \le 10^5 105nums[i]105

1.4 进阶

如果你已经实现复杂度为 O ( n ) O(n) O(n) 的解法,尝试使用更为精妙的分治法求解。

2. 解法一(动态规划)

2.1 分析

解答本题的关键在于正确定义 dp 数组以及找到状态转移方程,这里我们将 dp[i] 定义为以 nums[i] 结尾的子数组中元素和的最大值。

2.2 解答

from typing import List, Union


class Solution:
    def max_subarray(self, nums: List[int]) -> Union[int, float]:
        dp = [-float('INF')] * len(nums)  # dp[i] being the maximum element-wise sum of all sub arrays end with nums[i]
        dp[0] = nums[0]
        for i in range(1, len(dp)):
            dp[i] = max(dp[i - 1] + nums[i], nums[i])
        return max(dp)


def main():
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    sln = Solution()
    print(sln.max_subarray(nums))


if __name__ == '__main__':
    main()

  • 执行用时: 32 ms , 在所有 Python3 提交中击败了 93.03% 的用户;
  • 内存消耗: 15.2 MB , 在所有 Python3 提交中击败了 84.08% 的用户。

2.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n nnums 数组的长度。我们只需要遍历一遍数组即可求得答案。
  • 空间复杂度: O ( n ) O(n) O(n)。我们需要使用 dp 作为辅助存储容器。

实际上,上述解法还可以进一步优化以进一步提高算法的空间复杂度:

from typing import List, Union


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


def main():
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    sln = Solution()
    print(sln.efficient_max_subarray(nums))


if __name__ == '__main__':
    main()

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n nnums 数组的长度。我们只需要遍历一遍数组即可求得答案。
  • 空间复杂度: O ( 1 ) O(1) O(1)。我们只需要常数空间存放若干变量。

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/120359155
今日推荐