给你一个整数数组 nums
,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
如果题目要求找出数组中乘积最大的子数组对应的乘积,应该用什么方法呢?当然,我们需要找出数组元素所能组成的所有可能的子数组,然后对每一个子数组求乘积,最后返回最大乘积即可。解决这个问题需要使用回溯法,找到每一个可能的子数组。
但是该题要求子数组必须是连续的,如果继续使用回溯法,那么需要加入子数组是否是连续的判断逻辑。由于回溯法本身的时间复杂度就很高,再加入额外的逻辑会使得复杂度进一步变高,并不是最优解法。
对于连续子数组问题来说,当遍历到数组某一个位置时,它对于结果的改变只和前一个位置对应的情况有关。因此,可以使用动态规划来解。但是数组中元素有正有负,因此,对应的连续子数组的乘积也会有正有负。假设max
和min
分别表示当前的乘积最大值和最小值,对于某一个具体的位置来说:
- 如果当前位置
nums[i] > 0
,那么有max = MAX(max * nums[i], nums[i)
,min = MIN(min * nums[i], nums[i])
- 如果当前位置
nums[i] < 0
,那么max
和min
需要互换,保证max
和min
保存的依然是乘积的最大值和最小值
Java解题代码如下:
class Solution {
public int max = 1;
public int min = 1;
public int res = Integer.MIN_VALUE;
public int maxProduct(int[] nums) {
if(nums == null){
return 0;
}
for(int i = 0; i < nums.length; i++){
if(nums[i] < 0){
swap();
}
max = Math.max(max * nums[i], nums[i]);
min = Math.min(min * nums[i], nums[i]);
res = Math.max(res, max);
}
return res;
}
public void swap(){
int temp = max;
max = min;
min = temp;
}
}