一.题目描述:
给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-product-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二.思路
2.1 动态规划
我们发现乘积最大的子序列一定是已其中某个元素为结尾的(其实是一句废话),这样的话我们求出以所有元素结尾的子序列对应的最大乘积,然后取最大值即可
求以某个元素结尾的子序列 [...s[i]] 的最大值,我们可以根据以这个元素的前一个元素为结尾的子序列 [...s[i-1]] 的最大值来求。s[i]对应的最大值有两种情况,把这个max{[...s[i-1],s[i]],s[i]},也就是取把这个元素加到以s[i-1]结尾的子序列中去的最大值和s[i]的最大值
因为还有涉及到负数的问题,所以我们还需要存储最小值,当s[i]为负数时,将s[i-1]的最大值和最小值交换求s[i]对应的最大值。
其实是动态规划的思想,利用之前的遍历结果,但是没有一个明确的传统的迭代式子。
别人的讲解也讲的很好:
/**
* 解题思路:
* 最暴力的方式当然是遍历到i,都和i之前的再循环一遍,找到最大值,双重遍历
* 上面的解题时间会超,所以得考虑利用之前的遍历结果,==>动态规划
* <p>
* 求积的最大值,最麻烦的就是
* 当遇到0的时候,整个乘积会变成0;当遇到负数的时候,当前的最大乘积会变成最小乘积,最小乘积会变成最大乘积
* <p>
* 所以用两个数组进行保存最大值和最小值
* <p>
* 当前的最大值等于已知的最大值、最小值和当前值的乘积,当前值,这三个数的最大值。
* 当前的最小值等于已知的最大值、最小值和当前值的乘积,当前值,这三个数的最小值。
* 结果是最大值数组中的最大值。
AC代码:
class Solution:
def maxProduct(self, nums: List[int]) -> int:
imax=[0 for i in range(len(nums)+1)]
imax[0]=1
imin=[0 for i in range(len(nums)+1)]
imin[0]=1
Max=float("-inf")
for i in range(len(nums)):
if nums[i]<0:
imax[i+1]=max(imin[i]*nums[i],nums[i])
imin[i+1]=min(imax[i]*nums[i],nums[i])
else:
imax[i+1]=max(imax[i]*nums[i],nums[i])
imin[i+1]=min(imin[i]*nums[i],nums[i])
if imax[i+1]>Max:
Max=imax[i+1]
return Max
2.2