【简单】Leetcode-53 最大子序和

题目描述

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

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

解法一

暴力求解。思路简单,时间复杂度为 O(n*n),会超时

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        # 暴力
        if not nums: return 0
        res = nums[0]
        for l in range(len(nums)):
            for j in range(l, len(nums)):
                res = max(res, sum(nums[l:j+1]))
        return res

解法二

动态规划。比较迭代过程中比较当前值与 上一次的dp值的和是否有超过当前值,否则只保留当前值填入当前dp即可。时间复杂度O(n), 空间复杂度 O(n)

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        # 动态规划
        dp = [nums[0]] * len(nums)
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            # 如果当 num[i] > dp[i-1] + nums[i],那么可以表示之前的可以舍弃重新开始
            dp[i] = max(nums[i], dp[i-1] + nums[i])
        return max(dp)

解法三

动态规划。时间复杂度O(n), 空间复杂度 O(1)。

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        # 动态规划
        res = cur = nums[0]
        for i in range(1, len(nums)):
            cur = max(nums[i], cur + nums[i])
            res = max(res, cur)
        return res

解法四

回溯 + 分治。分为左中右。看注释理解中间区域

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if not nums: return 0
        return self.__max_sub_array(nums, 0, len(nums) - 1)

    def __max_sub_array(self, nums, left, right):
        if left == right:
            return nums[left]
        mid = left + ((right - left) >> 1)
        # 回溯 + 分治
        return max(self.__max_sub_array(nums, left, mid),
                   self.__max_sub_array(nums, mid + 1, right),
                   self.__max_cross_array(nums, left, mid, right))

    def __max_cross_array(self, nums, left, mid, right):
        # 一定包含 nums[mid] 元素的最大连续子数组的和,
        # 思路是看看左边"扩散到底",得到一个最大数,右边"扩散到底"得到一个最大数
        # 然后再加上中间数
        left_sum_max, start_left, s1 = 0, mid - 1, 0
        while start_left >= left:
            s1 += nums[start_left]
            left_sum_max = max(left_sum_max, s1)
            start_left -= 1

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

友情链接更多精彩内容