【每日刷题】乘积最大子序列

本文探讨了LeetCode上的一个问题——乘积最大子序列,给出了一种动态规划的解决方案。通过构建辅助数组pre记录负数位置,根据当前元素正负更新最大乘积dp[i]。虽然这种方法AC并具有较好运行时间,但还有更简洁的动态规划策略可供探索。
摘要由CSDN通过智能技术生成

题目地址

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, 且运行时间比较理想,但总体而言比较复杂。有一些更优的动态规划解法值得思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值