152. Maximum Product Subarray

来源:互联网 发布:cad技巧 知乎 编辑:程序博客网 时间:2024/05/22 16:51

题目

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

//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]为结尾的最大值与最小值(因为负负得正,所以也要保存最小值)