求子数组的最大积.
我一开始联想到的是子数组的最大和,动态规划经典题目,但是这道题好像不能用DP来解.
我采用的是一种很直观的解法,求子数组最大积的时候,最特殊的就是0,0乘任何数都等于0.所以,假设有这样的一个数组
1,4,-5,9,-3,-4,0,1,-4,9,7,-3
0把这个数组分成了两个子数组,则最大积就是这两个子数组最大积的最大值(大多数情况下是,暂时不考虑特殊边界条件).所以我们求两个子数组的最大积,那么问题就转换成:不含0的数组求子数组的最大积.
如果不含0的数组包含偶数个负数,则子数组的最大积为所有数字相乘.
如果不含0的数组包含奇数个负数,则子数组的最大积为:max(去除第一个负数及之前的元素所有数字的乘积,去除最后一个负数及之后的元素所有数字乘积).
原数组子数组最大积就是所有不含0的子数组,求子数组最大积,取最大值.
当然,如果所有不含0的子数组,求子数组最大积都为负,则子数组最大积为0,例如:
-2,0,-1这个测试用例.
class Solution {
public:
int maxProduct(vector<int>& nums) {
if(nums.empty()) return 0;
else if(nums.size()==1) return nums[0];
int zero_point=0;
int n=(int)nums.size();
int ret=INT_MIN;
int l=0;
while(zero_point<n){
while(zero_point<n && nums[zero_point]!=0) ++zero_point;
int t=maxProductWithoutZero(nums,l,zero_point);
//cout<<"t="<<t<<endl;
ret=max(ret,t);
while(zero_point<n && nums[zero_point]==0) ++zero_point;
//cout<<"zero_point="<<zero_point<<endl;
l=zero_point;
}
ret=max(ret,0);
return ret;
}
//array doesn't contain zero
//[l,r)
//return max product
int maxProductWithoutZero(vector<int>& nums,int l,int r){
//cout<<"l="<<l<<" r="<<r<<endl;
if(l==r-1) return nums[l];
else if(l==r) return 0;
int n=0;//amount of negetive number
int ret=1;
for(int i=l;i<r;++i){
if(nums[i]<=0) ++n;
}
if(n%2==0){
for(int i=l;i<r;++i) ret*=nums[i];
}else{
int a1=0;
for(a1=l;a1<r;++a1){
if(nums[a1]<0) break;
}
int num1=1;
for(int i=a1+1;i<r;++i) num1*=nums[i];
//cout<<"num1="<<num1<<endl;
int a2=r-1;
for(;a2>=0;--a2){
if(nums[a2]<0) break;
}
int num2=1;
for(int i=a2-1;i>=l;--i) num2*=nums[i];
//cout<<"num2="<<num2<<endl;
ret=max(num1,num2);
}
return ret;
}
};