Description
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.
分析
题目的意思是:找到一个连续子数组,使得它们的乘积最大。
1)如果当前元素为正数,那么极大值只可能扩大,所以应该继续扩展当前subarray:
2)如果当前元素为负数,那么极大值可能会变小,所以不清楚应该继续扩展当前subarray还是新起一个subarray:
3)如果当前元素为0,那么包括一个0会使得极大值成为0,而按照操作规定,这里的极大值应该大于等于1,所以应该舍弃当前元素,新起一个subarray.
对于第2中情况,我们用两个数组分别记录遍历的极大值和极小值,因此最大值只可能从nums[i],mums[i]*dp_max[i-1],nums[i]*dp_min[i-1]中产生。想一想看是不是这个道理。
C++
class Solution {
public:
int maxProduct(vector<int>& nums) {
int result=nums[0];
vector<int> dp_max(nums.size(),0);
vector<int> dp_min(nums.size(),0);
dp_max[0]=dp_min[0]=nums[0];
for(int i=1;i<nums.size();i++){
dp_max[i]=max(nums[i],max(dp_max[i-1]*nums[i],dp_min[i-1]*nums[i]));
dp_min[i]=min(nums[i],min(dp_max[i-1]*nums[i],dp_min[i-1]*nums[i]));
result=max(dp_max[i],result);
}
return result;
}
};
Python
这道题理论上需要一个两个dp来解决问题,因为要考虑负负得正,正正得正这两种情况,然后求根据两个dp得到的最大值。
dp_max[i]=max(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
dp_min[i]=min(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
class Solution:
def maxProduct(self, nums: List[int]) -> int:
# dp[0]=nums[0]
# dp_max[i]=max(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
# dp_min[i]=min(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
n=len(nums)
dp_max = [0]*n
dp_min = [0]*n
for i in range(n):
if i==0:
dp_max[i]=dp_min[i]=nums[0]
else:
dp_max[i]=max(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
dp_min[i]=min(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
res=dp_max[0]
for i in range(n):
res=max(dp_max[i],res)
return res
参考文献
[LeetCode] Maximum Product Subarray 求最大子数组乘积
[LeetCode] Maximum Product Subarray的4种解法