题目地址
https://leetcode-cn.com/problems/maximum-product-subarray/
题目描述: 乘积最大子序列
给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例:
例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
解答
首先要明确一点:使用动态规划解决问题。
方法一,我的解决办法:构建一个辅助数组 pre,其中存储了之前的一个负数的位置。
遍历数组,有两种情况:当前元素 now 为非负数时,dp[i] 存储max( now, nowdp[i-1]); 若当前元素now为负数时,需要向前走到最近的一个负数元素,即pre[i], 两个负数相乘变为正数,若 record[pre[i] - 1] 为正数,则需要将其乘上,得到temp,然后 dp[i] 为max(temp, nowdp[i-1]).
class Solution {
public:
vector<int> preNegative( vector<int>& nums){
vector<int> pre( nums.size(), -1);
for( int i = 0, pos = -1; i < nums.size(); i++){
if( pos > -1)
pre[i] = pos;
if( nums[i] < 0)
pos = i;
}
return pre;
}
int maxProduct(vector<int>& nums) {
if( nums.empty())
return 0;
vector<int> record( nums.size(), 0);
vector<int> pre = preNegative( nums);
//初始化
record[0] = nums[0];
int res = record[0];
//迭代
for( int i = 1; i < nums.size(); i++){
if( nums[i] < 0 && pre[i] != -1){
int temp = nums[i];
for( int j = i - 1; j >= pre[i]; j--)
temp *= nums[j];
if( pre[i] > 0 && record[ pre[i] - 1] > 0)
temp *= record[ pre[i] - 1];
record[i] = max( temp, nums[i] * record[i-1]);
}
else
record[i] = max( nums[i], nums[i] * record[i-1]);
res = max( res, record[i]);
}
return res;
}
};
上述方法成功 AC, 且运行时间比较理想,但总体而言比较复杂。有一些更优的动态规划解法值得思考。