P4095. 乘积最大子数组
题目内容
给你一个整数数组nums,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个32-位整数。
输入描述
一个整数数组nums
输出描述
一个整数表示最大乘积
样例1
输入
2 3 -2 4
输出
6
说明
子数组[2,3]有最大乘积6。
样例2
输入
-2 0 -1
输出
0
说明
结果不能为 2, 因为[-2,-1]不是子数组。
提示:
\(1 <= nums.length <= 2 * 10^4\)
\(-10 <= nums[i] <= 10\)
nums 的任何子数组的乘积都保证是一个 32-位 整数
由于数组中既可能有正数也可能有负数,负数相乘会使得结果变正,同时遇到 0 时会将乘积清零,因此我们需要同时记录当前子数组的最大值和最小值。具体思路如下:
定义 dp_{max}[i]表示以下标 i 结尾的子数组所能获得的最大乘积;
定义 dp_{min}[i]表示以下标 i 结尾的子数组所能获得的最小乘积;
当遇到负数时,由于负负得正,当前最大值可能由之前的最小值乘以当前值得到;
状态转移公式为
\(dp_{max}[i] = max(nums[i], dp_{max}[i-1] * nums[i], dp_{min}[i-1] * nums[i])\)
\(dp_{min}[i] = min(nums[i], dp_{min}[i-1] * nums[i], dp_{min}[i-1] * nums[i])\)
同时维护全局最大值即可。
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
int a[maxn];
int n=0,x;
int maxval[maxn];
int minval[maxn];
int ans=0;
int main(){
maxval[0]=1;
minval[0]=1;
while(cin>>x){
a[++n]=x;
}
for(int i=1;i<=n;i++){
maxval[i]=max(a[i],max(maxval[i-1]*a[i],minval[i-1]*a[i]));
minval[i]=min(a[i],min(minval[i-1]*a[i],maxval[i-1]*a[i]));
ans=max(ans,max(maxval[i],a[i]));
}
cout<<ans<<endl;
}