leetcode 152. 乘积最大子序列
152. 乘积最大子序列
问题描述
给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
问题分析
我怀疑题目错了,应该是乘积最大子数组,因为他要求是连续的数,这一点 问题53最大子序和不同,我们定义dp[i]
是以nums[i]结尾的nums[0,...,i]的乘积最大子序列,那么最简单的一种想法就是从nums[i]开始一直向前乘,找到最大的一个即可,但是这样的空间复杂度为O(n),时间复杂度为O(n^2),并不能让我们满意(见代码1)。首先我们发现dp[i]实际上是可以不需要的,因为他不依赖于前面的dp[i-1],可以使用一个maxnum来代替,见代码2。接下来我们使用问题53的思路,使用动态规划来求解该问题,这个问题独特的特点是如果遇到一个负数,如果前面最小的数也是负数,很有可能相乘成为最大的数,因此我们不光要追踪最大的数,同时还要追踪最小的数,其余思路和问题53相同。见代码3.
代码
//代码1:暴力方法
class Solution {
public:
int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
int i,j,tmp;
vector<int> dp(n,1);
dp[0] = nums[0];
int ans = dp[0];
for(i = 1; i < n; i++)
{
tmp = 1;
dp[i] = nums[i];
for(j = i; j >= 0; j--)
{
tmp *= nums[j];
if(dp[i] < tmp)
{
dp[i] = tmp;
}
}
if(dp[i] > ans)
ans = dp[i];
}
return ans;
}
};
//代码2:暴力方法
class Solution {
public:
int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
int i,j,tmp,maxnum;
int ans = nums[0];
for(i = 1; i < n; i++)
{
tmp = 1;
maxnum = nums[i];
for(j = i; j >= 0; j--)
{
tmp *= nums[j];
if(maxnum < tmp)
{
maxnum = tmp;
}
}
if(maxnum > ans)
ans = maxnum;
}
return ans;
}
};
//代码3:动态规划
class Solution {
public:
int maxProduct(vector<int>& nums) {
int n = nums.size();
if(n == 0) return 0;
int i,j,maxnum=nums[0],minnum = nums[0],ans = nums[0];
for(i = 1; i < n; i++)
{
if(nums[i] < 0)
{
swap(maxnum,minnum);
}
maxnum = max(maxnum*nums[i],nums[i]);
minnum = min(minnum*nums[i],nums[i]);
ans = max(ans,maxnum);
}
return ans;
}
};