给你一个整数数组nums,请你找出数组中乘积最大的非空连续子数组
(该子数组中至少包含一个数字),并返回该子数组所对应的乘积
测试用例的答案是一个32位整数
子数组是数组的连续子序列。
第一反应就是动态规划,然后记录每个位置的最大子数组.不过这样总是有问题
正确的方式是:使用动态规划,但是要同时记录每个位置的最大值和最小值,这是因为
- 如果当前位置是一个正数,那么它希望前面dp[i-1]位置的结果越大越好
- 如果当前位置是一个负数,那么它希望前面dp[i-1]位置的结果越小越好
所以单纯的如果只使用一个动态规划记录最大和的话 每个位置的结果并非是最优的解,当记录下最大和最小时,当前位置的最优一定能够找到
public int maxProduct(int[] nums) {
int len = nums.length;
int[] minDp = Arrays.copyOf(nums, nums.length);
int[] maxDp = Arrays.copyOf(nums, nums.length);
int ans = maxDp[0];
for (int i = 1; i < len; i++) {
maxDp[i] = Math.max(nums[i], Math.max(nums[i] * maxDp[i - 1], nums[i] * minDp[i - 1]));
minDp[i] = Math.min(nums[i], Math.min(nums[i] * maxDp[i - 1], nums[i] * minDp[i - 1]));
ans = Math.max(ans, maxDp[i]);
}
return ans;
}
还可以进行优化空间复杂度
public int maxProduct2(int[] nums) {
int len = nums.length;
int minDp = nums[0];
int maxDp = nums[0];
int ans = nums[0];
for (int i = 1; i < len; i++) {
int max = maxDp, min = minDp;
maxDp = Math.max(nums[i], Math.max(nums[i] * max, nums[i] * min));
minDp = Math.min(nums[i], Math.min(nums[i] * max, nums[i] * min));
ans = Math.max(ans, maxDp);
}
return ans;
}