• LeetCode(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.

    Subscribe to see which companies asked this question

    分析

    最大字段积问题,之前我们熟悉的题目是求最大字段和。其实,他们本质是相同的,应该属于动态规划的范畴。

    方法一(遗憾的TLE):
    由于最终的最大乘积结果可能是从0~size-1的任何一个位置开始的子数组,所以我们可以先求出从0~siz-1开始的每个位置到最终位置的最大乘积,保存起来。

    然后遍历该最大乘积数组,找出其中的最大值。

    该方法复杂度有O(n^2)吧,遗憾的是,TLE了。。。

    方法二:
    不得不再次思考效率高的算法:

    我们知道对序列元素遍历到 i 时,其值可正可负;
    最大值可能是:
    1. 前面子序列最大正乘积 * 正值;
    2. 前面子序列最小负乘积 * 负值;

    也就是说:其实子数组乘积最大值的可能性为:累乘的最大值碰到了一个正数;或者,累乘的最小值(负数),碰到了一个负数。所以每次要保存累乘的最大(正数)和最小值(负数)。
    同时,还有一个选择起点的逻辑,如果之前的最大和最小值同当前元素相乘之后,没有当前元素大(或小)那么当前元素就可作为新的起点。例如,前一个元素为0的情况,{1,0,9,2},到9的时候9应该作为一个最大值,也就是新的起点,{1,0,-9,-2}也是同样道理,-9比当前最小值还小,所以更新为当前最小值。

    TLE代码

    class Solution {
    public:
        int maxProduct(vector<int>& nums) {
            if (nums.empty())
                return 0;
    
            int size = nums.size();
            //求从0~size-1处开始,每处能够得到的最大子数组乘积
            vector<int> maxP(size, 1);
            for (int i = 0; i < size; ++i)
            {
                maxP[i] = nums[i];
            }//for
    
            for (int i = 0; i < size; ++i)
            {
                int curP = maxP[i];
    
                for (int j = i + 1; j<size; ++j)
                {
                    curP *= nums[j];
                    if (maxP[i] < curP)
                        maxP[i] = curP;
                }           
            }//for
    
            //找到最大子数组乘积中的最大乘积值
            int maxRet = maxP[0];
            for (int i = 1; i < size; ++i)
            {
                if (maxP[i] > maxRet)
                    maxRet = maxP[i];
            }//for
            return maxRet;
        }
    };

    AC代码

    class Solution {
    public:
        //方法一:遗憾的TLE
        int maxProduct1(vector<int>& nums) {
            if (nums.empty())
                return 0;
    
            int size = nums.size();
            //求从0~size-1处开始,每处能够得到的最大子数组乘积
            vector<int> maxP(size, 1);
            for (int i = 0; i < size; ++i)
            {
                maxP[i] = nums[i];
            }//for
    
            for (int i = 0; i < size; ++i)
            {
                int curP = maxP[i];
    
                for (int j = i + 1; j<size; ++j)
                {
                    curP *= nums[j];
                    if (maxP[i] < curP)
                        maxP[i] = curP;
                }           
            }//for
    
            //找到最大子数组乘积中的最大乘积值
            int maxRet = maxP[0];
            for (int i = 1; i < size; ++i)
            {
                if (maxP[i] > maxRet)
                    maxRet = maxP[i];
            }//for
            return maxRet;
        }
    
        //方法二:时间复杂度为O(n)
        int maxProduct(vector<int>& nums) {
            if (nums.empty())
                return 0;
    
            int size = nums.size();
    
            //存储最大子数组乘积,当前最大、最小值
            int maxRetP = nums[0], curMaxP = nums[0], curMinP = nums[0];
            for (int i = 1; i < size; ++i)
            {
                int tmpMax = curMaxP * nums[i];
                int tmpMin = curMinP * nums[i];
    
                //更新当前最大、最小值
                curMaxP = max(max(tmpMax , tmpMin), nums[i]);
                curMinP = min(min(tmpMax , tmpMin), nums[i]);
    
                //更新当前最大子数组结果
                maxRetP = max(maxRetP, curMaxP);
            }//for
            return maxRetP;
        }
    };
    

    GitHub测试程序源码

  • 相关阅读:
    【转载】Sqlserver存储过程中使用Select和Set给变量赋值
    【转载】腾讯云如何将一个域名解析到另一个域名上
    【转载】Sqlserver限制最大可使用内存
    【转载】 腾讯云通过设置安全组禁止某些IP访问你的服务器
    【转载】 C#使用Select方法快速获取List集合集合中某个属性的所有值集合
    【转载】哪些域名后缀可在工信部进行备案操作
    【转载】 C#使用string.Join快速用特定字符串串联起数组
    【转载】Sqlserver使用Convert函数进行数据类型转换
    【转载】Sqlserver根据生日计算年龄
    【转载】 腾讯云硬盘不够用,如何对硬盘进行扩容
  • 原文地址:https://www.cnblogs.com/shine-yr/p/5214779.html
Copyright © 2020-2023  润新知