Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.
Example 1:
Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:
Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.
tag: array,dynamic programming
method 1
单纯用Maximum Sum Subarray的方法来做本道题是错的,问题就在于dp[1]可能不仅和dp[i-1]有关,甚至和dp[i-2]有关,例如负,正,负的情况,在这样的情况下,dp不仅需要记录以i-1结尾的最大积,也需要记录以i-1结尾的最小积,因为如果异数相乘,就变成了一个负数
public int maxProduct(int[] nums) {
int[] dpMax = new int[nums.length];
int[] dpMin = new int[nums.length];
dpMax[0] = nums[0];
dpMin[0] = nums[0];
int res = nums[0];
for (int i = 1; i < nums.length; i++) {
dpMax[i] = Math.max(Math.max(dpMax[i-1]*nums[i],dpMin[i-1]*nums[i]),nums[i]);
dpMin[i] = Math.min(Math.min(dpMax[i-1]*nums[i],dpMin[i-1]*nums[i]),nums[i]);
res = Math.max(res,dpMax[i]);
}
return res;
}
method 2
对method 1的改进
使用两个变量来代替两个dp
public int maxProduct2(int[] A) {
if (A == null || A.length == 0) {
return 0;
}
int max = A[0], min = A[0], result = A[0];
for (int i = 1; i < A.length; i++) {
int temp = max;
max = Math.max(Math.max(max * A[i], min * A[i]), A[i]);
min = Math.min(Math.min(temp * A[i], min * A[i]), A[i]);
if (max > result) {
result = max;
}
}
return result;
}
method 3 two-pass
https://leetcode.com/problems/maximum-product-subarray/discuss/48302/2-Passes-scan-beats-99
public int maxProduct3(int[] nums) {
int max = Integer.MIN_VALUE, product = 1;
int len = nums.length;
for(int i = 0; i < len; i++) {
max = Math.max(product *= nums[i], max);
if (nums[i] == 0) product = 1;
}
product = 1;
for(int i = len - 1; i >= 0; i--) {
max = Math.max(product *= nums[i], max);
if (nums[i] == 0) product = 1;
}
return max;
}
summary:
- 当动态规划数组中,dp[i]只与dp[i-1]相关,那么这个时候可以用一个变量代替dp数组
- 考虑算法题的时候一定要尽量考虑清楚有哪些情况,不要忙着写代码,不然这样写出的代码也很难100%过测试用例的