一、题目
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
示例 1:
输入: nums = [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: nums = [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
提示:
- 1 <= nums.length <= 2 * 104
- -10 <= nums[i] <= 10
- nums 的任何前缀或后缀的乘积都 保证 是一个 32-位 整数
二、代码
class Solution {
public int maxProduct(int[] nums) {
// 上一个位置的乘积最小值
int preMax = nums[0];
// 上一个位置的乘积最小值
int preMin = nums[0];
// 当前找到的乘积最大值
int max = nums[0];
// 当前位置的乘积最大值
int curMax = 0;
// 当前位置的乘积最小值
int curMin = 0;
// 从左往右构造dp,求以i位置为结尾的子数组的最大累乘积
for (int i = 1; i < nums.length; i++) {
// 求最大值只有三种情况
// 1) i位置的数自己
// 2) i位置的数乘以i - 1位置的数的时候得到的最大累乘积
// 3) i位置的数乘以i - 1位置的数的时候得到的最小累乘积(因为有可能i位置是负数,然后再乘以前面计算结果最小值的负数就可以得到一个最大正数解)
// 计算得到当前位置的乘积最大值
curMax = Math.max(nums[i], Math.max(nums[i] * preMax, nums[i] * preMin));
// 计算得到当前位置的乘积最小值
curMin = Math.min(nums[i], Math.min(nums[i] * preMax, nums[i] * preMin));
// 找所有情况的最大值
max = Math.max(max, curMax);
// 将当前位置的信息赋值给pre,在下一轮计算的时候用
preMax = curMax;
preMin = curMin;
}
// 返回所有情况的最大值
return max;
}
}
三、解题思路
可能性分析(三种情况取最大值):
1) i位置的数自己
2) i位置的数乘以i - 1位置的数的时候得到的最大累乘积
3) i位置的数乘以i - 1位置的数的时候得到的最小累乘积(因为有可能i位置是负数,然后再乘以前面计算结果最小值的负数就可以得到一个最大正数解)