LeetCode 53/152 Maximum Subarray/Maximum Product Subarray(动态规划)

Leetcode 53-Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

分析:这题就是求最大连续字串的和,或者说是求和最大的连续子数组

此题最简单的是暴力,但是暴力为O(N^2), 超时。

另外可以采用动态规划来求解,关键是如何转换为动态规划问题,即如何表述成动态规划问题。

我们用local[i]来表示以A[i]结尾的连续子数组的最大和么local[0] = A[0], local[1]等于要么local[0]+A[1]  要么就等于A[1]本身,关键看两者谁更大,于是便得到递归式local[i+1] = max(local[i]+A[i+1], A[i+1]),local数组中的最大值即为所求。

参考链接: http://blog.csdn.net/lu597203933/article/details/44962163

典型的动态规划---"全局最优和局部最优解法"
1、基本思路
1)基本变量:全局最优,到当前元素的最优解
2)动态规划递推式:
假设我们已知第i步的global[i](全局最优)和local[i](局部最优),那么第i+1步的表达式是:
local[i+1]=max(A[i+1], local[i]+A[i]),
就是局部最优是一定要包含当前元素,
所以不然就是上一步的局部最优local[i]+当前元素A[i+1](因为local[i]一定包含第i个元素,所以不违反条件),
但是如果local[i]是负的,那么加上他就不如不需要的,所以不然就是直接用A[i+1];
global[i+1]=max(local[i+1],global[i]),
有了当前一步的局部最优,那么全局最优就是当前的局部最优或者还是原来的全局最优
(所有情况都会被涵盖进来,因为最优的解如果不包含当前元素,那么前面会被维护在全局最优里面,如果包含当前元素,那么就是这个局部最优)。
2、复杂度
1)时间上只需要扫描一次数组,所以时间复杂度是O(n)。
2)空间上我们可以看出表达式中只需要用到上一步local[i]和global[i]就可以得到下一步的结果,
所以我们在实现中可以用一个变量来迭代这个结果,不需要是一个数组,也就是如程序中实现的那样,
所以空间复杂度是两个变量(local和global),即O(2)=O(1)。

class Solution(object):
    def maxSubArray(self, nums):#时间复杂度O(n)
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums)==0:
            return 0
        maxsum=nums[0]
        currsum=nums[0]
        for i in range(1,len(nums)):
            #考虑以当前位置为结尾的子数组
            currsum=max(nums[i],currsum+nums[i])#当前元素的局部最优:1)当前元素 2)上一元素局部最优加上当前元素(保证是连续的子数组)
            maxsum=max(maxsum,currsum)#全局最优:当前最优与上一全剧最优的最大值
        return maxsum


Letcode152-Maximum Product Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

链接:https://leetcode.com/problems/maximum-product-subarray/

这道题跟 Maximum Subarray 模型上和思路上都比较类似,还是用一维动态规划中的“局部最优和全局最优法”。这里的区别是维护一个局部最优不足以求得后面的全局最优,这是由于乘法的性质不像加法那样,累加结果只要是正的一定是递增,乘法中有可能现在看起来小的一个负数,后面跟另一个负数相乘就会得到最大的乘积。我们只需要在维护一个局部最大的同时,在维护一个局部最小,这样如果下一个元素遇到负数时,就有可能与这个最小相乘得到当前最大的乘积和,这也是利用乘法的性质得到的。

以max_local[i]表示以A[i]结尾的连续数组的最大乘积,min_local[i]表示以A[i]结尾的连续数组的最小乘积,转移方程为:

max_copy[i] = max_local[i]

max_local[i + 1] = Max(max_local[i] * A[i+1], A[i+1],  min_local * A[i+1])

min_local[i + 1] = Min(max_copy[i] * A[i+1], A[i+1],  min_local * A[i+1])

说明:在max_local[i] * A[i+1], A[i+1],  min_local * A[i+1]选出最小和最大的值,作为当前的局部最大最小值

参考链接:http://blog.csdn.net/linhuanmars/article/details/39537283

class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        if len(nums)==1:
            return nums[0]

        max_local=nums[0]
        min_local=nums[0]
        max_global=nums[0]
        for i in range(1,len(nums)):
            max_copy=max_local
            max_local=max(max_local*nums[i],nums[i],min_local*nums[i])
            min_local=min(max_copy*nums[i],nums[i],min_local*nums[i])
            max_global=max(max_local,max_global)
        return max_global




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值