LeetCode 最大子序和

题目

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

示例

input: [-2, 1, -3, 4, -1, 2, 1, -5, 4]
output: 6

解法


动态规划 ( Python )
class Solution:
    def maxSubArray(self, nums) -> int:
        tmp = nums[0]
        maxlen = tmp
        for i in range(1, len(nums)):
            if(tmp < 0):
                tmp = nums[i]
            else:
                tmp += nums[i]
            maxlen = max(maxlen, tmp)
        return maxlen
基本思路

   动态规划的思想是最优解包含的每个子问题的解也是最优的。代码中的tmp代表的就是子问题的最优解,不过因为这道题中有负数的存在,所以子问题的最优解也可能是负数,所以还需要和 0 进行比较。另外,这道题没有代价的概念,只有值的累加,不需要保存每个子问题的最优解,只需要上一轮的最优解即可。maxlen变量不是主角,其作用只是记录当前最大值而已。

复杂度分析

  for循环的时间开销为 O ( N ) O(N) O(N),内部为O(1),所以时间复杂度为 O ( N ) O(N) O(N)。空间复杂度为 O ( 1 ) O(1) O(1)

分冶法 ( Python )
class Solution:
    def maxSubArray(self, nums) -> int:
        length = len(nums)
        if(length <= 0):
            return 0
        return self.calSubArray(nums, 0, length - 1)
        
    def calSubArray(self, nums, left, right):
        if(left == right):
            return nums[left]
        mid = (left + right) // 2
        maxleft = self.calSubArray(nums, left, mid)
        maxright = self.calSubArray(nums, mid + 1, right)
        
        #从mid为起点,向左计算最大子序列和, ct意为continuity,连续的
        tmp = 0
        left_ct = nums[mid]
        for i in range(mid, left - 1, -1):
            tmp += nums[i]
            left_ct = max(tmp, left_ct)
        
        #以mid为起点,向右计算最大子序列和
        tmp = 0
        right_ct = nums[mid + 1]
        for i in range(mid + 1, right + 1):
            tmp += nums[i]
            right_ct = max(tmp, right_ct)
    
        #计算左右子序列交界地带最大子序列和
        maxCross = left_ct + right_ct
        return max(maxleft, maxright, maxCross)
基本思路

  分冶法是将原问题逐步划分成一个个更小的子问题,再合并的过程。maxleftmaxright是被划分出的左右两个序列的最大子序和,但这两者是不能直接相加的,因为它们在序列里有可能不是连续的。另外,这两个序列原先是交接的,它们的交界地带有可能存在一个更大的子序列和,所以需要以mid为起点,分别向左右两边累加,求得交界地带最大值。下面举两个例子。

input: [2, -1, 2]
说明:这个序列会被划分成[2], [-1, 2]两个子序列。
	 最大子序列和分别为 2,2。但因为两个2索引不是连续的,所以不能直接相加

input: [-1, 2, 1, 2, -1, 1]
说明:这个序列会被划分成[-1, 2, 1][2, -1, 1]。
	 左侧最大序列和为 2,右侧最大序列和也是2。但是它们的交界地带有一个更大的子序列[2, 1, 2]
复杂度分析

  分冶法的时间复杂度为 O ( N 2 ) O(N^2) O(N2), 因为calSubArray被调用了n次,这和二分法是不同的,另外递归实现也会带来一定的开销。空间复杂度为 O ( 1 ) O(1) O(1)

参考资料
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值