152. Maximum Product Subarray

#题目
Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.
#思路
这道题目是典型的连续子序列的计算问题,接下来我们将使用三种算法来解决这个问题,分别是:浅显算法;两个平方算法;扫描算法。接下来结合代码来详细说明。
#代码
##浅显算法
最浅显的程序就是对所有满足0<=i<=j<n的整数进行迭代。对每个整数对,程序都要计算nums[i…j]的总和,并检验该总和是否大于迄今为止的最大总和。如下:

//solution 1:最浅显的程序就是对所有满足0<=i<=j<n的整数进行迭代。
//对每个整数对,程序都要计算nums[i..j]的总和,并检验该总和是否大于迄今为止的最大总和。
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int maxsofar = INT_MIN, product;
        for(int i=0;i<nums.size();i++)
            for(int j=i;j<nums.size();j++)
            {
                product =1;
                for(int k=i;k<=j;k++)
                    product = product*nums[k];
                maxsofar = max(maxsofar,product);
            }
        return maxsofar;
    }
};

上述代码简洁、直观并且易于理解,但是嵌套使用了三个for循环。因为也被称为立方算法。该方法时间复杂度很高,因此提交超时了。
152
##平方算法
在前面一个算法中,我们在计算nums[i…j]的总乘积与前面已计算出的nums[i…j-1]总乘积密切相关。因为可与利用这个关系的到一个平方算法。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int maxsofar = INT_MIN, product;
        for(int i=0;i<nums.size();i++)
        {
            product = 1;
            for(int j=i;j<nums.size();j++)
            {
                product = product*nums[j];
                maxsofar = max(maxsofar,product);
            }
        }
        return maxsofar;
    }
};

该方法运用了两个for循环,时间复杂度依旧比较高,提交结果依旧超时。
##扫描算法
我们现在采用操作数组最简单的算法:从数组最左端(元素nums[0])开始扫描,一直到最右端(元素nums[n-1])为止,并记下所遇到的最大乘积子向量。最大乘积的初始值设为nums[0]。假设我们解决了nums[0…i-1]的问题,那么如何将其扩展为包含nums[i]的问题呢?我们使用类似于分治算法的原理:**前i个元素中,最大总乘积子数组要么在前i-1个元素中(我们将其存储在maxsofar中),要么其结束位置为i(我们将其存储在maxendinghere中)。

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int maxsofar = nums[0];
        for(int i=1,maxend=maxsofar,minend=maxsofar;i<nums.size();i++)
        {
            
            if(nums[i]<0)
                swap(maxend,minend);
            maxend = max(nums[i],maxend*nums[i]);
            minend = min(nums[i],minend*nums[i]);
            maxsofar = max(maxsofar,maxend);            
        }
        return maxsofar;
    }
};

上述代码我们用两个变量maxend与minend来保存以nums[i]为结尾的最大值与最小值(因为负负得正,所以也要保存最小值)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roaring Kitty

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值