leetcode : Maximum Product Subarray
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.
神马复杂度为n^2,n^3的解法肯定是会超时的,ok目标为O(n);
以max[i]表示从任意不大于i的位置开始,一直连乘直到i,得到的积中最大的那一个。以pro(i)表示分别从1,2 ...i连乘到i所得到的积的集合。
那么如何得到max[i]呢? 我们知道max[i]所对应的集合pro(i)是由pro(i-1)中每一个元素乘以A[i],再加上A[i]本身得到的,那么显然的,max[i]只能通过以下三种途径得到:
1.最大值就是A[i]本身
2.若A[i] > 0,那么最大值就是pro(i-1)中的最大正数乘以A[i]
3.若A[i] < 0, max就等于pro中最小的负数乘以A[i]
那么问题来了,pro(i-1)中的最大正数以及最小负数怎么求得呢? 仔细考虑便可以想到,是由pro(i-2)中的最大正数以及最小负数得到的。更一般的,可以将这个最小负数 退化为最小的数,最大正数退化为最大的数,这样在处理的过程中可以不针对最小值不是负数等情况作出特殊处理。
所以我们可以用递归方式,求每一个i的最大正数,最小负数,以及A[i]
int max(i) {
a = MIN( pro(i - 1) );
b = MAX( pro(i - 1) );
c = A[i];
max = max(a, b, c);
return max;
}
int MIN( pro(i) ){
a = MIN( pro(i - 1) );
b = MAX( pro(i - 1) );
c = A[i];
return min(a, b, c);
}
//MAX(pro(i))的伪代码不在赘述,同MIN大同小异。
但是,在从max[i] 到 max[1]的求解过程中,MAX(pro xx), MIN(pro xx) 重复求解了非常多次
考虑动态规划的两个特点:
1.最优子结构
2.子问题重复
所以我们可以用动态规划的方式优化求解算法,并且使用 备忘录 保存每个pro(i)的最大最小值。将递归问题转化成动态规划 + 备忘录 方式以空间换时间
由于我们并不关心pro(n)以外的最大最小值,所以进一步优化 备忘录 的结构,即只用两个单位空间分别保存当前的最大 最小值
AC 代码
class Solution { public: int maxProduct(int A[], int n) { if(n == 1) return A[0]; int currentMin = A[0],currentMax = A[0]; int ret = max(currentMin,currentMax); for(int i = 1; i < n; ++i){ int preMin = currentMin, preMax = currentMax; currentMin = min(A[i], min(A[i] * preMin, A[i] * preMax)); currentMax = max(A[i], max(A[i] * preMin, A[i] * preMax)); ret = max(ret,currentMax); } return ret; } };
浙公网安备 33010602011771号