题目
给定一个整数数组 nums
,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
思路
使用动态规划方法。
最朴素的想法,需要将每一种子数组都考虑到,即时间复杂度为O(n^2)
。
如何降低时间复杂度呢?最理想化的算法也需要遍历一次数组,即O(n)
。
求相邻数组的最大值,在第i个位置只有两种取值的可能性:
(1)取nums[i]
值;
(2)nums[i-1]时的最大值与nums[i]相乘,即maxNum[i-1]*nums[i]
;
此题还有一个特殊情况,就是数组可以取负值,若nums[i]为负值,则最大值的取值两种情况为:
(1)取nums[i]
值;
(2)nums[i-1]时的最小值与nums[i]相乘,即minNum[i-1]*nums[i]
;
因此需要两个数组分别存储数组的最大值和最小值,以此来求出整个数组的子区间最大值。
代码
class Solution {
public int maxProduct(int[] nums) {
//算法复杂度O(n^2)->O(n)
//只扫描1次
int len = nums.length;
int max = nums[0];
int[] maxNum = new int[len];
int[] minNum = new int[len];
maxNum[0]=nums[0];
minNum[0]=nums[0];
for(int i=1; i<len; i++){
if(nums[i]>=0){
maxNum[i] = Math.max(nums[i],maxNum[i-1]*nums[i]);
minNum[i] = Math.min(nums[i],minNum[i-1]*nums[i]);
}else{
maxNum[i] = Math.max(nums[i],minNum[i-1]*nums[i]);
minNum[i] = Math.min(nums[i],maxNum[i-1]*nums[i]);
}
max = Math.max(max,maxNum[i]);
}
return max;
}
}
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)