zoukankan      html  css  js  c++  java
  • 【LeetCode】152.乘积最大子数组

    题目链接

    https://leetcode-cn.com/problems/maximum-product-subarray/

    题目描述

    给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

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

    解题思路

    1.暴力枚举

    双重for循环,以数组中每个下标开始,迭代更新乘积最大的连续子数组。时间复杂度O(n2)

    2.动态规划

    首先本题与LC 53.最大子序和类似,53题的转移方程为dp[i]=max(dp[i-1]+nums[i],nums[i]),dp[i]仅仅与前一个状态有关,因为题目要求是连续子数组。回到本题中,如果只考虑数组中只会出现正数,那么这道题就和53题的思路是一样的,状态转移方程也是一样的:dp[i]=max(dp[i-1]*nums[i],nums[i]),但是本题中数组中是会出现不定个数的负数,如果只有一个负数,上述状态转移方程是没有问题的,但是如果出现两个负数就会产生问题,因为负负得正,比如数组[2,3,-3,-4]。,那么第一个符号之前所有的乘积就都要考虑在dp[i]里面,但是用上述方程,早在第一个负数出现的时候,它前面的乘积都已经丢掉了,所以这才是为什么还需要记录一个最小值,说白了,最小值只有是负数出现的时候才会在这道题发挥它的用处,否则,最小值和最大值都是一样的。所以对于dp[i]来说,dp[i-1]可能是最大值也可能是最小值,若nums[i]>0,则dp[i-1]记录的是>0的最大值,则没问题,若nums[i]<0,dp[i-1]就应该记录的是<0的最小值,这样才能产生最大值。所以改进后的状态转移方程如下:

    maxF[i] = max(minF[i - 1] * nums[i], max(nums[i], maxF[i - 1] * nums[i]));
    minF[i] = min(maxF[i - 1] * nums[i], min(nums[i], minF[i - 1] * nums[i]));

    AC代码

    1.暴力枚举(超时)

     1 class Solution {
     2 public:
     3     int maxProduct(vector<int>& nums) {
     4         int ans = INT_MIN;
     5         for(int i = 0; i < nums.size(); i++)
     6         {
     7             int val = 1;
     8             for(int j = i; j < nums.size(); j++)
     9             {
    10                 val = val * nums[j];  //迭代更新乘积最大的连续子数组
    11                 if(val > ans) ans = val; //迭代更新乘积最大的连续子数组
    12             }
    13         }
    14         return ans;
    15     }
    16 };

    2.动态规划

     1 class Solution {
     2 public:
     3     int maxProduct(vector<int>& nums) {
     4         vector <int> maxF(nums), minF(nums);
     5         int ans = max(INT_MIN,nums[0]);
     6         for (int i = 1; i < nums.size(); ++i) {
     7             maxF[i] = max(minF[i - 1] * nums[i], max(nums[i], maxF[i - 1] * nums[i]));
     8             minF[i] = min(maxF[i - 1] * nums[i], min(nums[i], minF[i - 1] * nums[i]));
     9             ans = max(ans,maxF[i]);
    10         }
    11         return ans;
    12     }
    13 };

    因为当前状态只有前一个状态有关,所以可以把空间复杂度从O(n)优化至O(1)

    优化后的动态规划

     1 class Solution {
     2 public:
     3     int maxProduct(vector<int>& nums) {
     4         int maxf = 1;
     5         int minf = 1;
     6         int ans = INT_MIN;
     7         for(int i = 0; i < nums.size(); i++)
     8         {
     9             int aa = maxf;   //利用aa记录尚未更新的maxf的值。
    10             maxf = max(minf*nums[i],max(maxf*nums[i],nums[i]));
    11             minf = min(aa*nums[i],min(minf*nums[i],nums[i]));
    12             ans = max(ans,maxf);
    13         }
    14         return ans;
    15     }
    16 };
  • 相关阅读:
    导入导出通用库
    镜像下载地址
    后端请求接口的几种方式
    获取本机的mac地址
    Arduino串口的一些高级用法
    手机与Arduino蓝牙串口通讯实验及完整例程
    ARDUINO+MCP2515实现CAN通讯接收
    Arduino IIC 主从设备连接通信
    上位机与单片机的通信问题
    NRF24L01多对一、多通道通讯关键代码
  • 原文地址:https://www.cnblogs.com/XDU-Lakers/p/12913331.html
Copyright © 2011-2022 走看看