53. Maximum Subarray 最大子序和 code

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

思路:

遍历法:
先看 O(n) 的解法,定义两个变量 res 和 curSum,其中 res 保存最终要返回的结果,即最大的子数组之和。curSum 初始值为0,每遍历一个数字 num,比较 curSum + num 和 num 中的较大值存入 curSum,然后再把 res(保存的是上一次curSum和res的最大值) 和 curSum 中的较大值存入 res,以此类推直到遍历完整个数组,可得到最大子数组的值存在 res 中,代码如下:

from typing import List
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        else:
            curSum = 0
            res = 0
            for num in nums:
                curSum = max(curSum+num,num)
                res = max(res, curSum)
        return res
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)
# list
from typing import List
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        else:
            curSum = [0 for i in range(len(nums))] #长度为len(nums)值为0的list
            curSum.append(nums[0])
            res = curSum[0]
            for i in range(1,len(nums)):
                curSum[i] = max(curSum[i-1]+nums[i],nums[i])
                res = max(res, curSum[i])
        return res
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)

分治法 Divide and Conquer Approach:
其思想类似于二分搜索法,需要把数组一分为二,分别找出左边和右边的最大子数组之和,然后还要从中间开始向左右分别扫描,求出的最大值分别和左右两边得出的最大值相比较取最大的那一个,代码如下:

from typing import List
class Solution(object):
    def maxSubArray(self, nums: List[int]) -> int:
        """
        :type nums: List[int]
        :rtype: int
        """
        return self.divideMethod(nums, 0, len(nums) - 1)
 
    def divideMethod(self, nums, i, j):
        if i == j:
            return nums[i]
        divide = (i + j) // 2
        
        ls = nums[divide]
        rs = nums[divide + 1]
#         left
        sum = 0
        for k in range(divide + 1, j + 1):
            sum += nums[k]
            if sum >= rs:
                rs = sum
#         right     
        sum = 0
        for k in range(divide, i - 1, -1):
            sum += nums[k]
            if sum >= ls:
                ls = sum     
        maxSum = ls + rs
        
        leftMaxSum = self.divideMethod(nums, i, divide)
        rigthMaxSum = self.divideMethod(nums, divide + 1, j)
        
        if leftMaxSum >= maxSum:
            maxSum = leftMaxSum
        if rigthMaxSum >= maxSum:
            maxSum = rigthMaxSum
        return maxSum   

nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)

动态规划:
将求n个数的数组的最大子段和,转换为分别求出以第1个、第2个、…第i个、…、第n个数字结尾的最大字段和,再找出这n个结果中最大的,即为结果。

第i个状态(dp[i])即为以第i个数字结尾的最大子段和(最优解)。由于以第i-1个数字结尾的最大子段和(dp[i-1])与nums[i]相邻:

# 动态规划
from typing import List
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 0:
            return 0
        else:
            dp = [0 for i in range(len(nums))] # 长度为len(nums)值为0的list
            dp.append(nums[0])
            maxnum = dp[0]
            for i in range(1,len(nums)):
                dp[i] = max(dp[i-1]+nums[i],nums[i])
                if dp[i] > maxnum:
                   maxnum = dp[i]
        return maxnum
nums = [-2,1,-3,4,-1,2,1,-5,4]
solution = Solution()
solution.maxSubArray(nums)

(仔细想想和遍历法是一样的)

猜你喜欢

转载自blog.csdn.net/Frank_LJiang/article/details/106212069