题目
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-product-subarray
方法1:动态规划
作者:guanpengchn
链接:https://leetcode.cn/problems/maximum-product-subarray/solution/hua-jie-suan-fa-152-cheng-ji-zui-da-zi-xu-lie-by-g/
来源:力扣(LeetCode)
思路:
这道题是【LeetCode-中等】53. 最大子数组和(详解)的难度升级版
都是一种动态规划然而53题是求和最大值,这里是求乘积最大值
求和最大值比较简单:遍历数组,记录下每个位置的最大数组和,最后找到最大的即可。、
没做过上一题的可以先去看看上面的链接博客中的方法2,看懂那个便于做这道题。
这道题也是一样,区别在于:这道题有 负数
有负数就说明我们不能一直求最大的,例如[2,3,-5,-2],如果你一直求当前最大,那你就不会去乘这个-5,你的错误答案就会变成“6”,然而真确答案应该是“60”,具体怎么修改,看下面思路。
遍历数组时计算当前最大值,不断更新
令imax为当前最大值,则当前最大值为 imax = max(imax * nums[i], nums[i])
由于存在负数,那么会导致最大的变最小的,最小的变最大的。
因此还需要维护当前最小值imin,imin = min(imin * nums[i], nums[i])
当负数出现时则imax与imin进行交换再进行下一步计算
代码:
class Solution {
public int maxProduct(int[] nums) {
int len = nums.length;
int max = Integer.MIN_VALUE;
int imin = 1;
int imax = 1;
for (int i = 0; i < len; i++) {
if (nums[i] < 0){
int temp = imin;
imin = imax;
imax = temp;
}
imax = Math.max(nums[i] , imax * nums[i]);
imin = Math.min(nums[i] , imin * nums[i]);
max = Math.max(max , imax);
}
return max;
}
}
动态规划真是妙,思路很妙,代码很简洁,一定要 学会这两道动态规划的题:最大数组和、乘积最大数组