leetcode 152. 乘积最大子序列

152. 乘积最大子序列

问题描述

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

问题分析

我怀疑题目错了,应该是乘积最大子数组,因为他要求是连续的数,这一点 问题53最大子序和不同,我们定义dp[i]
是以nums[i]结尾的nums[0,...,i]的乘积最大子序列,那么最简单的一种想法就是从nums[i]开始一直向前乘,找到最大的一个即可,但是这样的空间复杂度为O(n),时间复杂度为O(n^2),并不能让我们满意(见代码1)。首先我们发现dp[i]实际上是可以不需要的,因为他不依赖于前面的dp[i-1],可以使用一个maxnum来代替,见代码2。接下来我们使用问题53的思路,使用动态规划来求解该问题,这个问题独特的特点是如果遇到一个负数,如果前面最小的数也是负数,很有可能相乘成为最大的数,因此我们不光要追踪最大的数,同时还要追踪最小的数,其余思路和问题53相同。见代码3.

代码

//代码1:暴力方法
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        if(n == 0) return 0;
        int i,j,tmp;
        vector<int> dp(n,1);
        dp[0] = nums[0];
        int ans = dp[0];
        for(i = 1; i < n; i++)
        {
            tmp = 1;
            dp[i] = nums[i];
            for(j = i; j >= 0; j--)
            {
                tmp *= nums[j];
                if(dp[i] < tmp)
                {
                    dp[i] = tmp;
                } 
            }
            if(dp[i] > ans)
                ans = dp[i];
        }
        return ans;
    }
};
//代码2:暴力方法
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        if(n == 0) return 0;
        int i,j,tmp,maxnum;
        int ans = nums[0];
        for(i = 1; i < n; i++)
        {
            tmp = 1;
            maxnum = nums[i];
            for(j = i; j >= 0; j--)
            {
                tmp *= nums[j];
                if(maxnum < tmp)
                {
                    maxnum = tmp;
                } 
            }
            if(maxnum > ans)
                ans = maxnum;
        }
        return ans;
    }
};
//代码3:动态规划
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int n = nums.size();
        if(n == 0) return 0;
        int i,j,maxnum=nums[0],minnum = nums[0],ans = nums[0];
        for(i = 1; i < n; i++)
        {
            
            if(nums[i] < 0)
            {   
                swap(maxnum,minnum);
            }
            maxnum = max(maxnum*nums[i],nums[i]);
            minnum = min(minnum*nums[i],nums[i]);
            ans = max(ans,maxnum);
        }
        return ans;
    }
};
posted @ 2019-11-21 16:24  曲径通霄  阅读(99)  评论(0编辑  收藏  举报