您的位置:首页 > 其它

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

2018-01-04 11:19 423 查看
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]结尾的连续
4000
子数组的最大和,那么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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: