题目:
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4]
,
the contiguous subarray [2,3]
has the largest product = 6
.
思路:
动态规划。
这道题类似于求最大子序列和。在求最大子序列和时,会比较当前值与当前值加上前面子序列的和,保留较大的一个。而在求最大乘积时,由于0和负数的存在,不能只考虑保留乘积最大的部分,还要考虑保留乘积最小的部分。
代码为:
int maxProduct(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
int n=nums.size();
vector<int> maxPro(n,0),minPro(n,0);
maxPro[0]=nums[0];
minPro[0]=nums[0];
int res=nums[0];
for(int i=1;i<n;++i){
maxPro[i]=max(nums[i],max(nums[i]*maxPro[i-1],nums[i]*minPro[i-1]));
minPro[i]=min(nums[i],min(nums[i]*maxPro[i-1],nums[i]*minPro[i-1]));
res=max(res,maxPro[i]);
}
return res;
}
另外一个思路是我自己在做题时想的,比上文提到的思路繁琐,但时间复杂度也为O(n),先记录如下:
思路:
首先把0作为一个分界点,遇到0时,先找到前面序列的最大子序列乘积,在接下来的过程中,前面的子序列不在考虑。
在其中一段子序列中,记录下负数的个数,子序列的乘积tmpPro,从子序列开始到第一个负数的乘积subPro1和从最后一个负数到子序列最后的乘积subPro2,具体例子如下:
序列 -2,3,4,-3,3,1,-5,3
这里tmpPro=-3240,subPro1=-2,subPro2=-5*3=-15。由于负数个数为奇数,就有可能出现第一个负数为分界点和最后一个负数为分界点的情况,这里就需要比较tmpPro/subPro1和tmpPro/subPro2,选择其中最大的子序列乘积。同时这里也需要注意:
1)序列中有0,0等类似的情况,这时tmpPro=1,不能作为子序列的乘积,在这里加入tmpValid标记变量tmpPro是否可用
2)子序列中只有一个负数的情况,如-2,用上面的方法就会出现除数为1的情况,在这里加入subValid标记变量subPro1是否可除
代码:
在这段代码中,可以现在nums后插入0,这样就不用在最后又重复一段代码。
int maxProduct(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
int maxPro=nums[0];
int negNum=0;
int tmpPro=1;
int subPro1=1;
int subPro2=1;
bool tmpValid=0;
bool subValid=0;
for(int i=0;i<nums.size();++i){
if(nums[i]==0 ){
if(tmpValid){
if(negNum%2==0)
maxPro=max(maxPro,tmpPro);
else{
if (negNum == 1 && !subValid)
maxPro = max(maxPro, tmpPro);
else
maxPro = max(maxPro, max(tmpPro / subPro1, tmpPro / subPro2));
}
}
maxPro=max(maxPro,0);
tmpPro=1;
negNum=0;
subPro1=1;
subPro2=1;
tmpValid=0;
subValid=0;
}else{
tmpPro*=nums[i];
tmpValid=1;
if(nums[i]<0){
if(negNum==0)
subPro1*=nums[i];
subPro2=nums[i];
negNum++;
}else{
if(negNum==0)
subPro1*=nums[i];
else
subPro2*=nums[i];
subValid=1;
}
}
}
if(tmpValid){
if(negNum%2==0)
maxPro=max(maxPro,tmpPro);
else{
if (negNum == 1 && !subValid)
maxPro = max(maxPro, tmpPro);
else
maxPro = max(maxPro, max(tmpPro / subPro1, tmpPro / subPro2));
}
}
return maxPro;
}