题意:给定一个数组,求最大连续子数组的乘积。
感觉是dp但是没想出来。简单版本的题目是连续子数组的和,这里面状态定义是以i为结尾的最大子数组的和。需要定义以i为结尾而不是[0,..,i]区间内某个子数组的和,是因为子数组是连续的,以i为结尾可以直接从dp[i-1]转移到dp[i]。
但是求和问题的正数负数都有累加效应,比如,如果是正数往子数组中添加加会一直增大,负数就会一直减小。但是乘积没有这种单调性,比如乘上连续的几个负数,乘积是正负交替变化。
正解是维持两个dp状态,一个是记录以i结尾的最大值,一个是记录以i结尾的最小值。如此,遇到正数,最大值相乘还是最大值;遇到负数,最小值相乘会变成最小值。
class Solution {
public:
int maxProduct(vector<int>& nums) {
vector<int>preprod=vector<int>(nums.size());
int res=nums[0];
vector<int>maxi=vector<int>(nums.size());
vector<int>mini=vector<int>(nums.size());
maxi[0]=nums[0];
mini[0]=nums[0];
for(int i=1;i<nums.size();i++)
{
if(nums[i]>0)
{
maxi[i]=max(nums[i],maxi[i-1]*nums[i]);
mini[i]=min(nums[i],mini[i-1]*nums[i]);
}
else
{
maxi[i]=max(nums[i],mini[i-1]*nums[i]);
mini[i]=min(nums[i],maxi[i-1]*nums[i]);
}
// cout<<maxi[i]<<endl;
res=max(res,maxi[i]);
}
return res;
}
};