要求:
给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
示例:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
思路:
动态规划:
base case:最初的最大值或最小值必是第一个数本身
dp[2][len]:创建一个两行,len列的数组,第一行存储当前的最大值,第二行存储当前的最小值。
状态转移:
1. 如果nums[i]>=0, 那么dp[0][i]=Math.max(nums[i], dp[0][i-1]*nums[i]), dp[1][i]=Math.min(nums[i], dp[1][i-1]*nums[i])。因为倘若之前的最大值为正数,最小值为负数,nums[i]为正,但是否比1大未知,所以在自身和乘之前的最大值里选。
2. 同理,若nums[i]<0,那么dp[0][i] = Math.max(nums[i], dp[1][i-1]*nums[i]),dp[1][i] = Math.min(nums[i], dp[0][i-1]*nums[i])。
代码:
class Solution {
public int maxProduct(int[] nums) {
int len = nums.length;
int[][] dp = new int[2][len];
dp[0][0] = nums[0];
dp[1][0] = nums[0];
if (len == 0) return 0;
for (int i = 1; i < len; i++) {
if (nums[i] >= 0) {
dp[0][i] = Math.max(nums[i], nums[i] * dp[0][i-1]);
dp[1][i] = Math.min(nums[i], nums[i] * dp[1][i-1]);
} else {
dp[0][i] = Math.max(nums[i], nums[i] * dp[1][i-1]);
dp[1][i] = Math.min(nums[i], nums[i] * dp[0][i-1]);
}
}
int res = dp[0][0];
for (int i = 0; i < len; i++) {
res = Math.max(res, dp[0][i])
}
return res;
}
}