152. Maximum Product Subarray
Description:
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
.
Solution:
一、题意理解
给定一个int型的数组,找到乘积最大的子序列,返回这个乘积。
二、分析
1、很明显是动态规划题。
2、因为数组中的数有正有负,可能本来某个序列乘积是负的,很小,但是如果下一个数是负数,负负得正,就会立即使乘积变 的很大,所以我们不仅要维护一个局部最大值,也要维护一个局部最小值,当然还有一个全局最大值。
3、列出如下的动态规划方程。
(1)设curmax为局部最大值,curmin为局部最小值,max为全局最大值,初始值均为curmax = curmin = max = A[0];
(2)for i = 1 to n-1:
// 先保存一下局部最大值
temp = curmax;
// 将“curmax * A[i]”、“A[i]”、“curmin * A[i]” 三者比较,取最大值赋值给curmax
curmax = MAX( MAX(curmax * A[i], A[i]), curmin*A[i]);
// 将“curmin * A[i]”、“A[i]”、“temp * A[i]” 三者比较,取最小值赋值给curmin
curmin = MIN( MIN(curmin * A[i], A[i]), temp * A[i]);
// 保存全局最大值
max = MAX(max, curmax);
(3)遍历完成后,max即是最大乘积。
4、代码如下:
#define MAX(x,y) (x>y? x:y)
#define MIN(x,y) (x<y? x:y)
class Solution {
public:
int maxProduct(int A[], int n) {
if(n==1)
return A[0];
int curmax = A[0];
int curmin = A[0];
int max = A[0];
int temp;
for(int i=1;i<n;i++)
{
temp = curmax;
curmax = MAX( MAX(curmax*A[i],A[i]), curmin*A[i] );
curmin = MIN( MIN(curmin*A[i],A[i]), temp*A[i]);
max = MAX(max, curmax);
}
return max;
}
};
三、结果及优化
1、Runtime: 16ms
2、看到Solutions中有3ms的解法,去瞻仰一番,意思是可以证明出:
(1) 假设在A[]中没有0存在,那么结果必是A[0] A[1] .... A[i] 或 A[j] *A[j+1] A[n - 1]。
(2) 如果A[]中有0存在(假设A[k] == 0),那么可以将数组拆分为A[0],A[1]...A[k - 1 ] 和 A[k + 1] A[k + 2]...A[n-1] 两个数组,然后再应用(1)即可。
3、怎么证明的我也不知道,大致想了一下,可以分奇数个负数和偶数个负数来讨论。贴上大神的代码:
class Solution {
public:
int maxProduct(int A[], int n) {
int frontProduct = 1;
int backProduct = 1;
int ans = INT_MIN;
for (int i = 0; i < n; ++i) {
frontProduct *= A[i];
backProduct *= A[n - i - 1];
ans = max(ans,max(frontProduct,backProduct));
frontProduct = frontProduct == 0 ? 1 : frontProduct;
backProduct = backProduct == 0 ? 1 : backProduct;
}
return ans;
}
};