解法参考自评论区的大佬。
解法1:
最大子序列的乘积只有在一种情况下为负:只有一个元素且该元素为负。
设想序列中间的一个数,如果它的左边和右边为均为正或均为负,则可以将它们加入子序列,乘积一定是变大的;如果左边和右边为一正一负,则必然可以加入其中一个。
只有遇到0时比较特殊,需要从0后的第一个非0元素重新开始计算。
所以,我们只需要从前往后累乘,从后往前累乘,取整个过程中最大的值即可。
int maxProduct(vector<int>& nums){
int l2r,r2l;//从左到右累乘,从右到左累乘
l2r=nums[0];
r2l=nums[nums.size()-1];
int lmax=l2r;//从左到右累乘的最大值
int rmax=r2l;//从右到左累乘的最大值
if(nums.size()==1) return lmax;
for(int i=1;i<nums.size();++i){
if(l2r==0){
l2r = nums[i];
}
else
l2r*=nums[i];
if(r2l==0){
r2l = nums[nums.size()-1-i];
}
else
r2l*=nums[nums.size()-1-i];
lmax=max(lmax,l2r);
rmax=max(rmax,r2l);
}
return max(lmax,rmax);
}
解法2:DP
用imax和imin分别表示到i为止的最大值和最小值
如果遇到负数,imax和imin要交换
int maxProduct(vector<int>& nums){
int imin=1;
int imax=1;
int _max=INT_MIN;
for(int i=0;i<nums.size();++i){
if(nums[i]<0){
int tmp = imin;
imin=imax;
imax=tmp;
}
imax=max(imax*nums[i],nums[i]);
imin=min(imin*nums[i],nums[i]);
_max=max(_max,imax);
}
return _max;
}