zoukankan      html  css  js  c++  java
  • 【LeetCode-动态规划】乘积最大子数组

    题目描述

    给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字)。
    示例:

    输入: [2,3,-2,4]
    输出: 6
    解释: 子数组 [2,3] 有最大乘积 6。
    
    输入: [-2,0,-1]
    输出: 0
    解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
    

    思路

    因为是求乘积,而且数组中正负数都有,所以会出现最大值乘以负数变成最小值以及最小值乘以负数变成最大值的情况,所以我们要维护两个dp数组:dpMax和dpMin,dpMax[i]为以i为结尾的最大的序列乘积,dpMin[i]为以i为结尾的最小的序列乘积。分两种情况分析:

    • 当nums[i]>=0时:
      • dpMax[i] = max(dpMax[i-1]*nums[i], nums[i]);
      • dpMin[i] = min(dpMin[i-1]*nums[i], nums[i]);
    • 当nums[i]<0时:
      • dpMax[i] = max(dpMin[i-1]*nums[i], nums[i]);
      • dpMin[i] = min(dpMax[i-1]*nums[i], nums[i]);

    综上,有:

    • dpMax[i] = max(dpMax[i-1]*nums[i], nums[i], dpMin[i-1]*nums[i]);
    • dpMin[i] = min(dpMin[i-1]*nums[i], nums[i], dpMax[i-1]*nums[i]);

    对应代码如下:

    class Solution {
    public:
        int maxProduct(vector<int>& nums) {
            if(nums.empty()) return 0;
    
            int dpMax[nums.size()], dpMin[nums.size()];
            memset(dpMax, 0, sizeof(dpMax));
            memset(dpMin, 0, sizeof(dpMin));
            int maxPro = nums[0];
            dpMax[0] = nums[0];
            dpMin[0] = nums[0];
            for(int i=1; i<nums.size(); i++){
                dpMax[i] = max(max(dpMax[i-1]*nums[i], nums[i]), dpMin[i-1]*nums[i]);
                dpMin[i] = min(min(dpMax[i-1]*nums[i], nums[i]), dpMin[i-1]*nums[i]);
                maxPro = max(dpMax[i], maxPro);
            }
            return maxPro;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    空间复杂度优化:
    可以不使用dp数组,只使用两个变量。代码如下:

    class Solution {
    public:
        int maxProduct(vector<int>& nums) {
            if(nums.empty()) return 0;
    
            int curMax = nums[0];
            int curMin = nums[0];
            int maxPro = nums[0];
            for(int i=1; i<nums.size(); i++){
                int temp = curMax;    // 因为curMax在下一行可能会被更新,所以保存下来
                curMax = max(max(curMax*nums[i], nums[i]), curMin*nums[i]);
                curMin = min(min(curMin*nums[i], nums[i]), temp*nums[i]);
                maxPro = max(curMax, maxPro);
            }
            return maxPro;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)
  • 相关阅读:
    SP1716 GSS3
    A Simple Problem with Integers题解
    P4528 [CTSC2008]图腾 题解
    P1498 南蛮图腾 题解
    P2024 [NOI2001]食物链 题解
    Windows编程 Windows程序的生与死(中)
    Windows编程 Windows程序的生与死(上)
    C#实现在注册表中保存信息
    沿路径动画(Animation Along a Path)
    倾斜动画(SkewTransform)
  • 原文地址:https://www.cnblogs.com/flix/p/12739233.html
Copyright © 2011-2022 走看看