题目描述:
Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.
Example 1:
Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:
Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
题目大意:
- 如题目所示,相乘最大的子数组,给定你一个数组,让你找出子数组相乘最大的值
- 然后返回那个最大值
解题思路:
- 声明:此题为动态规划标签下,下面上动规
- Step1:确定dp table含义,既然题目如此,dp table含义也就相对明确了,就是dp[i]的值代表着以第i个数结尾的子数组的乘积最大值
- 接下来如果能找到一个递推关系,用dp table的前一个数值可以推出下一个数值,那么大功告成了,直接填表即可,最后返回一下dp table 的最大值,即为答案
- 但是此题不同于之前的一道标签为easy的最大子数组加和的那道题,见链接:LeetCode算法题之53. Maximum Subarray(easy)【Python3动态规划题解】
- 因为本人试了很多种想法,发现这个相乘与相加不一样,如果按照上述dp table 的定义方法,貌似每个位置的最大相乘值与前一个没啥关系,这个递推关系很难找到,主要原因还是给定数组里面有负数在捣乱
- 所以dp table 的定义得改,因为这个相乘啊,前一个数乘以后一个数的值,与这个后一个数的值的大小,只有两种可能,不是它大就是它大,当然相等是不影响下面分析的
- 但是重点是,虽然当前有一个数会小,但是不代表那个小的数,在乘以它下一个数时候,也还是小,举个例子:[-2, 3, -4],最大乘积值是多少?24啊,但是在3那个位置时候,前面-2 x 3=-6,与3相比,3大,但是,-6 x -4=24,比3 x -4=-12,要大,这就是上面那一堆说的意思
- 所以,这个dp table 得这样定义,dp[i][0]与dp[i][0]分别代表前一个数乘以后一个数的暂时小的值和暂时大的值,然后在另外设置一个变量,用来记录每个位置上最大的那个乘积值,这样遍历一次,就找到了那个答案,时间复杂度O(n)
- 看代码,一目了然
少废话,上代码:
class Solution:
def maxProduct(self, nums):
# 定义dp table,并初始化
dp = [[nums[0], nums[0]] for i in range(len(nums))]
# 初始化最大值变量,假设就是第一个
max_value = nums[0]
# 从第二个数开始遍历,依次计算每个位置上的乘积
for i in range(1, len(nums)):
# 下面就是递推公式,因为每次需要记录两个数
# 这一次的小数,也就是dp[i][0],未必在下一次的乘积中小
# 这一次的大数,dp[i][1],也是同理
# 所以都要计算,且记录
dp[i][0] = min(nums[i], dp[i-1][0]*nums[i], dp[i-1][1]*nums[i])
dp[i][1] = max(nums[i], dp[i-1][0]*nums[i], dp[i-1][1]*nums[i])
# 记录一下每次最大的值
max_value = max(max_value, max(dp[i]))
return max_value
运行时间和内存占用:
- Runtime: 64 ms, faster than 28.30% of Python3 online submissions for Maximum Product Subarray.
- Memory Usage: 16.3 MB, less than 6.90% of Python3 online submissions for Maximum Product Subarray.