53:最大子序和

53. 最大子序和

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

示例:

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

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

Python solution 1:

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        
        curSum = maxSum = nums[0]
        for num in nums[1:]:
            curSum = max(num, curSum + num)
            maxSum = max(curSum, maxSum)
        
        return maxSum

分析:

在这种方法中,curSum既是指针又是结果的保存器:如果num之前的连续 k 项之和比 num 小,那么 curSum 充当指针,它会指向当前的 num;反之,它会存储包括 num 在内的连续 k+1 项之和:

curSum = max(num, curSum + num)

这一行代码之所以能够保证是连续的 k 项之和,就在于它起到了指针的作用:如果 curSum 移动了,那么求和子序列就会从 num 处重新开始累加,从而保证了子序列的连续性(不会跳过当前的数而去和后面的数相加);如果指针没有移动,那么它会存储连续的 k+1 项之和。

curSum 的作用是负责遍历 nums 中所有可能的求和情况,它并不能保证在遍历完 nums 后 curSum 中存储的就是最大的子序和,因为在它找到最大子序和后,如果此时 nums 还没有遍历完,那它就要继续遍历 nums,从而有可能导致这个最大的子序和被别的数字代替。因此程序中又用到了 maxSum 这个存储器,其目的就是为了将 curSum 找到的那个最大的子序和保存下来。

Python solution 2:

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(1, len(nums)):
            if nums[i-1] > 0:
                nums[i] += nums[i-1]
        
        return max(nums)

分析:

这个方法是基于这样一种思想:任给一个数字 m,假如我们想让这个数字变大,现在让它加上另外一个数 n,那么当 n 满足什么条件时 m 才会变大呢?显然,只有当 n 是一个正数的时候 m 才会变大。

现在假如给定一个序列 nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4],我们想要从中找到最大连续子序和,考虑从序列中的第一个元素开始,一个一个进行判断。判断的标准是这样的:

如果前面一个数为正数,那就让后面紧邻的那个数加上前面的这个数,并让二者之和替换掉后面紧邻的这个数;

否则,什么都不做。

按照这个原则,最终 nums 将变成:nums = [-2, 1, -2, 4, 3, 5, 6, 1, 5],从而此时的 max(nums) 就是要找的最大连续子序和。

posted @ 2019-07-16 13:25  mingyu02  阅读(130)  评论(0编辑  收藏  举报