Problem
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.
Analysis
- Dp - 记录局部最优子结构 - 动态状态转移,集greedy和recursive大成
想好dp状态的含义:
- (Memory Limit Exceeded)第一反应,记录所有subarray的值,然后比较;dp[i,j]表示nums[i] * nums[i+1] … * nums[j] 的? dp[i,j] = dp[i,j-1]*dp[j,j]
// dp[i,j] = dp[i,j-1] * dp[j,j]
public int maxProduct(int[] nums) {
int len = nums.length;
if (len < 1) return 0;
int[][] dp = new int[len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (j < i) dp[i][j] = 1;
else if (j == i) dp[i][j] = nums[j];
else dp[i][j] = dp[i][j-1]*nums[j];
}
}
int res=Integer.MIN_VALUE;
for(int i=0;i < len; i++){
for (int j = 0; j < len; j++) {
if(j<i) continue;
res = Math.max(res, dp[i][j]);
}
}
return res;
}
- dpMax[i]表示[k, i]子数组最大值,1<= k <= i
- dpMin[i]表示[k, i]子数组最小值,1<= k <= i
dpMax=Math.max(Math.max(dpMax* nums[i], dpMin* nums[i]), nums[i]);
dpMin= Math.min(Math.min(dpMax * nums[i], dpMin * nums[i]), nums[i]);
- 空间复杂度进一步降低,因为只需要两个状态最大和最小,之前的状态都不需要保留。空间复杂度O(1)
public int maxProduct(int[] nums) {
int len = nums.length;
if (len < 1) return 0;
// int[] dpMax = new int[len];
// int[] dpMin = new int[len];
int dpMax = nums[0];
int dpMin = nums[0];
int res = dpMax;
for (int i = 1; i < len; i++) {
int tmp = Math.max(Math.max(dpMax* nums[i], dpMin* nums[i]), nums[i]);
dpMin= Math.min(Math.min(dpMax * nums[i], dpMin * nums[i]), nums[i]);
dpMax = tmp;
res = Math.max(res, dpMax);
}
return res;
}