算法:动态规划 最大连续子数组和 Maximum Subarray

题目

53. Maximum Subarray

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

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.

Example 1:

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6

Explanation: [4,-1,2,1] has the largest sum = 6.
Example 2:

Input: nums = [1]
Output: 1

Example 3:

Input: nums = [0]
Output: 0

Example 4:

Input: nums = [-1]
Output: -1

Example 5:

Input: nums = [-2147483647]
Output: -2147483647

Constraints:

1 <= nums.length <= 2 * 104
-2^31 <= nums[i] <= 2^31 - 1

动态规划解法

题意是求数组中子数组的最大和,这种最优问题一般第一时间想到的就是动态规划,我们可以这样想,当部分序列和大于零的话就一直加下一个元素即可,并和当前最大值进行比较,如果出现部分序列小于零的情况,那肯定就是从当前元素算起。其转移方程就是 dp[i] = nums[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);,由于我们不需要保留 dp 状态,故可以优化空间复杂度为 1,即 dp = nums[i] + (dp > 0 ? dp : 0);。

class MaxmumSubarray:
    def maxSubArray(self, nums: List[int]) -> int:
        if nums == None or len(nums) == 0:
            return 0
        for i in range(1, len(nums)):
            if nums[i - 1] > 0:
                nums[i] += nums[i - 1]
        return max(nums)

分而治之解法

题目也给了我们另一种思路,就是分治,所谓分治就是把问题分割成更小的,最后再合并即可,我们把 nums 一分为二先,那么就有两种情况,一种最大序列包括中间的值,一种就是不包括,也就是在左边或者右边;当最大序列在中间的时候那我们就把它两侧的最大和算出即可;当在两侧的话就继续分治即可。

class MaxmumSubarray:
    def maxSubArray(self, nums: List[int]) -> int:
        return self.helper(nums, 0, len(nums) - 1)

    def helper(self, nums: List[int], left: int, right: int) -> int:
        if left >= right:
            return nums[left]
        mid = (int)((left + right) / 2)
        leftSub = self.helper(nums, left, mid)
        rightSub = self.helper(nums, mid+1, right)
        leftMax = nums[mid]
        rightMax = nums[mid + 1]
        temp = 0
        for i in range(mid, left - 1, -1):
            temp += nums[i]
            if temp > leftMax:
                leftMax = temp

        temp = 0
        for k in range(mid+1, right + 1):
            temp += nums[k]
            if temp > rightMax:
                rightMax = temp

        return max(max(leftSub, rightSub), leftMax + rightMax)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值