leetcode 152. 乘积最大子序列 medium
题目描述:
给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
解题思路:
方法一: 暴力解 (O(n^2))
求以每个元素为开头的乘积最大子序列
方法二: 动规 O(n)
我们求以每个位置为结尾的最大乘积子序列,这是这类题用动规的常规思路,那么当前位置和前一个位置的关系怎么求呢?一开始我也卡在这,因为当前位置的最优解,不一定就是 前一个位置的最优解乘以当前数和当前数的最大值,比如
【2,3,-2,-2,4】这组数组,后来知道了,当前位置的最大值就是 1. 前一个位置的最大值乘以当前数,2.前一个位置的最小值乘以当前数 3. 当前数, 3者中的最大值。
所以我们需要求每个位置为结尾的最大值和最小值,用两个dp数组,当然也能用空间压缩技巧
代码:
//暴力解
class Solution {
public:
int maxProduct(vector<int>& nums) {
if(nums.empty())
return 0;
int n=nums.size();
int res=INT_MIN;
for(int i=0;i<n;++i){
int one=nums[i];
res = max(res,one);
for(int j=i+1;j<n;++j){
one *= nums[j];
res= max(res,one);
if(one==0) break;
}
}
return res;
}
};
//dp
class Solution {
public:
int maxProduct(vector<int>& nums) {
if(nums.empty())
return 0;
// dp 保存以每个元素为结尾的 乘积最大值和最小值
int n=nums.size();
int res=nums[0];
vector<int> dp_min(n);
vector<int> dp_max(n);
dp_max[0]=dp_min[0]=nums[0];
for(int i=1;i<nums.size();++i){
dp_max[i]=max(dp_max[i-1]*nums[i],max(dp_min[i-1]*nums[i],nums[i]));
dp_min[i]=min(dp_max[i-1]*nums[i],min(dp_min[i-1]*nums[i],nums[i]));
res = max(res,dp_max[i]);
}
return res;
}
};