Question
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
Example
For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6.
Tags
LinkedIn Dynamic Programming Subarray
Related Problems
Medium Best Time to Buy and Sell Stock 41 %
Medium Maximum Subarray Difference 23 %
Easy Minimum Subarray 38 %
Medium Maximum Subarray II
Analysis
本题其实是Maximum Subarray Sum问题的延伸,不同的是这里需要考虑元素的符号。
DP的四要素
状态:
max_product[i]
: 以nums[i]结尾的max subarray product
min_product[i]
: 以nums[i]结尾的min subarray product
方程:
max_product[i] = getMax(max_product[i-1] * nums[i], min_product[i-1] * nums[i], nums[i])
min_product[i] = getMin(max_product[i-1] * nums[i], min_product[i-1] * nums[i], nums[i])
初始化:
max_product[0] = min_product[0] = nums[0]
结果:
每次循环中 max_product[i]
的最大值
Solution
DP, with O(n) space, O(n) time
Copy public class Solution {
/**
* @param nums: an array of integers
* @return : an integer
*/
public int maxProduct ( int [] nums) {
int [] max = new int [ nums . length ]; // maximum product ending with nums[i]
int [] min = new int [ nums . length ]; // minimum product ending with nums[i]
max[ 0 ] = min[ 0 ] = nums[ 0 ];
int result = max[ 0 ];
for ( int i = 1 ; i < nums . length ; i ++ ) {
max[i] = min[i] = nums[i];
if (nums[i] > 0 ) { // 区分nums[i]的符号
max[i] = Math . max (max[i] , nums[i] * max[i - 1 ]);
min[i] = Math . min (min[i] , nums[i] * min[i - 1 ]);
} else {
max[i] = Math . max (max[i] , nums[i] * min[i - 1 ]);
min[i] = Math . min (min[i] , nums[i] * max[i - 1 ]);
}
result = Math . max (max[i] , result);
}
return result;
}
}
DP - Simplified - O(n) space, O(1) time
Copy class Solution {
public int maxProduct ( int [] nums) {
if (nums == null || nums . length == 0 ) return 0 ;
int n = nums . length ;
int [] maxProduct = new int [n]; // max subarray product ending in nums[i]
int [] minProduct = new int [n]; // min subarray product ending in nums[i]
maxProduct[ 0 ] = nums[ 0 ];
minProduct[ 0 ] = nums[ 0 ];
int max = maxProduct[ 0 ];
for ( int i = 1 ; i < n; i ++ ) {
maxProduct[i] = Math . max (nums[i] , Math . max (maxProduct[i - 1 ] * nums[i] , minProduct[i - 1 ] * nums[i]));
minProduct[i] = Math . min (nums[i] , Math . min (maxProduct[i - 1 ] * nums[i] , minProduct[i - 1 ] * nums[i]));
max = Math . max (maxProduct[i] , max);
}
return max;
}
}
DP, improved, with O(1) space, O(n) time
Copy public class Solution {
/**
* @param nums: an array of integers
* @return : an integer
*/
public int maxProduct ( int [] nums) {
int result , currentMax , currentMin;
result = currentMax = currentMin = nums[ 0 ];
for ( int i = 1 ; i < nums . length ; i ++ ) {
int temp = currentMax;
currentMax = Math . max (nums[i] , Math . max (currentMax * nums[i] , currentMin * nums[i]));
currentMin = Math . min (nums[i] , Math . min (temp * nums[i] , currentMin * nums[i]));
result = Math . max (currentMax , result);
}
return result;
}
}
O(1) space, O(n) time
Copy class Solution {
public int maxProduct ( int [] nums) {
if (nums == null || nums . length == 0 ){
return 0 ;
}
int maxPre = nums[ 0 ] , minPre = nums[ 0 ] , max = nums[ 0 ] , maxHere , minHere;
for ( int i = 1 ; i < nums . length ; i ++ ){
maxHere = Math . max (nums[i] , Math . max (nums[i] * maxPre , nums[i] * minPre));
minHere = Math . min (nums[i] , Math . min (nums[i] * maxPre , nums[i] * minPre));
max = Math . max (max , maxHere);
maxPre = maxHere;
minPre = minHere;
}
return max;
}
}
Same idea but a more concise implementation
Copy 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;
}
Reference