一、题目详情
原题链接:152. 乘积最大子数组
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
示例1:
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
提示:
-
1 <= nums.length <= 2 * 10的4次
-
-10 <= nums[i] <= 10
-
nums 的任何前缀或后缀的乘积都 保证 是一个 32位 整数
二、解题方法
1.法一:DP
我们用 fmax(i) 来表示以第 i 个元素结尾的乘积最大子数组的乘积,a(i)是当前数字,fmin(i) 来表示以第 i 个元素结尾的乘积最小子数组的乘积,考虑正负可得如下公式:
class Solution {
public int maxProduct(int[] nums) {
int len=nums.length;
int[] maxF=new int[len];
int[] minF=new int[len];
System.arraycopy(nums,0,maxF,0,len);
System.arraycopy(nums,0,minF,0,len);
for(int i=1;i<len;i++){
maxF[i]=Math.max(maxF[i-1]*nums[i],Math.max(nums[i],minF[i-1]*nums[i]));
minF[i]=Math.min(maxF[i-1]*nums[i],Math.min(nums[i],minF[i-1]*nums[i]));
}
int ans=maxF[0];
for(int i=1;i<len;i++){
ans=Math.max(ans,maxF[i]);
}
return ans;
}
}
复杂度分析 :
时间复杂度:O(N)
空间复杂度:O(N)
2.法二:DP+滚动数字 降低空间复杂度至O(1)
maxF、minF表示当前最大、最小的子数组乘积,mx、mn表示前一个最大、最小的子数组乘积。
class Solution {
public int maxProduct(int[] nums) {
int len=nums.length;
int maxF=nums[0],minF=nums[0],ans=nums[0];
for(int i=1;i<len;i++){
int mx=maxF,mn=minF;
maxF=Math.max(mx*nums[i],Math.max(nums[i],mn*nums[i]));
minF=Math.min(mx*nums[i],Math.min(nums[i],mn*nums[i]));
ans=Math.max(ans,maxF);
}
return ans;
}
}
复杂度分析 :
时间复杂度:O(N)
空间复杂度:O(1)