第一种特别麻烦的解法:先把数组按照0划分成一段一段的,然后根据每段负数值的个数,来求每段的最大乘积。
int maxProduct(vector<int>& nums)
{
vector<int> minusRec;
vector<int> zeroRec(1, -1);
vector<int> prodRec; // 每段的乘积
int res = nums[0];
// 用0来给nums分段,统计每一段内负数的个数
int count = 0;
int prod = 1;
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] == 0)
{
minusRec.push_back(count);
if(i - zeroRec[zeroRec.size() - 1] == 1)
prodRec.push_back(0);
else
prodRec.push_back(prod);
zeroRec.push_back(i);
prod = 1;
count = 0;
continue;
}
if(nums[i] < 0)
count++;
prod *= nums[i];
}
minusRec.push_back(count);
if(nums[nums.size() - 1] == 0)
prodRec.push_back(0);
else
prodRec.push_back(prod);
zeroRec.push_back(nums.size()); // zeroRec表示每一段的开始index和最后的index,如果没有0,则为{-1, nums.size()}
for(int i = 0; i < minusRec.size(); i++)
{
int begin = zeroRec[i];
int end = zeroRec[i + 1];
int temp = prodRec[i];
//如果段内有偶数个负数,则全段乘积为最大乘积
//如果段内有奇数个负数
if(end - begin > 2 && minusRec[i] % 2 != 0)
{
int left = 1, right = 1;
for(int j = begin + 1; j < end; j++) // 左起第一个负数左边的乘积(包括该负数)
{
left *= nums[j];
if(nums[j] < 0)
break;
}
for(int j = end - 1; j > begin; j--) // 右起第一个负数右边的乘积(包括该负数)
{
right *= nums[j];
if(nums[j] < 0)
break;
}
temp /= max(left, right); // 最大值为全段乘积除以左边或右边
}
res = max(temp, res);
}
if(zeroRec.size() > 2) // 如果数组中有0,应该和0比较。
res = max(res, 0);
return res;
}
第二种方法是从前向后遍历一遍再从后向前遍历一次,找到过程中的最大乘积。
int maxProduct(vector<int>& nums)
{
int res = nums[0], product = 1;
for(int i = 0; i < nums.size(); i++)
{
product *= nums[i];
res = max(product, res);
if(nums[i] == 0)
product = 1;
}
product = 1;
for(int i = nums.size(); i > 0;)
{
product *= nums[--i];
res = max(product, res);
if(nums[i] == 0)
product = 1;
}
return res;
}
第三种方法是看discuss里面一种只遍历一次的方法,遍历的时候同时记录最大值和最小值。
int maxProduct(int A[], int n) {
// store the result that is the max we have found so far
int r = A[0];
// imax/imin stores the max/min product of
// subarray that ends with the current number A[i]
for (int i = 1, imax = r, imin = r; i < n; i++) {
// multiplied by a negative makes big number smaller, small number bigger
// so we redefine the extremums by swapping them
if (A[i] < 0)
swap(imax, imin);
// max/min product for the current number is either the current number itself
// or the max/min by the previous number times the current one
imax = max(A[i], imax * A[i]);
imin = min(A[i], imin * A[i]);
// the newly computed max value is a candidate for our global result
r = max(r, imax);
}
return r;
}