力扣152:乘积最大子数组

力扣152:乘积最大子数组

题目

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

测试用例的答案是一个 32-位 整数。

思路

这道题我们首先想到的思路应该是动态规划,定义一个一维数组dp每一个位置i都存包含当前位置的最大乘积,这个最大乘积是当前值nums[i]和dp数组的前一个位置乘上当前位置

dp[i-1]*nums[i]的最大值。然后再定义一个整数用来保存整个过程中的最大乘积,用这种方法是可以过一部分的用例的但是会遇到一个很大的问题就是题目里没有说这个数组是一个正数数组也就是说这个数组是有负数的,用我们上面那个方法在遇到负数时肯定就判断最大乘积是当前值了因为乘一个负数肯定会变小嘛,那么问题就出现了在遇到一个负数后我们又遇到了一个正数此时最大乘积就变成了这个正数的值,在后面我们又遇到一个负数这时候的最大乘积就变成了这个负数。这就有问题了,乘一个负数值是会变小的但是乘两个负数值是会变大的啊。所以当数组里有两个负数时最后的子数组应该是会包含到这两个负数的但是实际我们的答案并不会因为我们遇到负数就更新最大乘积是当前负数的值了,这就是我们的问题。想要对这个动态规划做优化的话我们就需要对这个负数情况做处理。

但是现在我不用这种方法了我们想一想其他的思路,在经过上面的分析时发没发现一个情况那就是子数组的两边是不可能都有负数的因为只要乘上这两个负数整个的乘积是肯定会变大的啊,还有就是子数组的任意一侧是不可能有正数的,一样的情况乘上这个正数整个的乘积是会变大的而我们求得就是最大乘积。所以这就导致了我们最后的子数组的两端一定是0或者是数组的起止位置。那么我们是否可以定义两个整数i,j来代表从头到尾的下标以及从尾到头的下标。同时再定义两个整数pre,bck分别存储从头到尾的乘积和从尾到头的乘积。这时候整个数组我们可以分为三种情况

  1. 数组都是非负数
    这种情况又包含数组里有0和没有0,有0时pre和bck就会分别求得0前面的子数组的乘积和和0后面的子数组的乘积和,最终答案肯定就是这两个其中一个。没有0的时候pre和bck的值最后是一样的,子数组就是原数组。
  2. 数组有奇数个负数
    奇数个负数时pre和bck也会各自求得负数前面的子数组的和和负数后面的子数组的和。
  3. 数组有偶数个负数
    偶数个负数等于就是都是正数,也就是直接获得整个数组的乘积和。

注意:第二种和第三种情况都是在数组没有0的情况下,如果有0就参考第一种情况,逻辑是一样的。

在经过上面三种情况的讨论后我们就可以定义一个整数res来当最大乘积也就是答案了,在移动pre和bck时我们也需要判断res的值,那么是从哪几个值里找最大值呢有四个值即res,当nums[i],pre,bck。可能会有疑惑为什么要带上nums[i]呢,我直接举例子大家就知道了当数组为[-2,0,-1]时,最大乘积不就是0吗。所以带上nums[i]是因为子数组有可能只有一个元素。

代码

cpp 复制代码
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = INT_MIN;
        int i = 0;
        int j = nums.size() - 1;
        //从前往后的乘积
        int pre = 1;
        //从后往前的乘积
        int bck = 1;
        while (i < nums.size()) {
            pre *= nums[i];
            bck *= nums[j];
            //比较res,nums[i],pre,bck的值,找到最大值
            res = max(max(res, nums[i]), max(pre, bck));
            //遇到零就重新计算
            if (nums[i] == 0)
                pre = 1;
            if (nums[j] == 0)
                bck = 1;
            i++;
            j--;
        }
        return res;
    }
};
相关推荐
YGGP1 小时前
【Golang】LeetCode 128. 最长连续序列
leetcode
你撅嘴真丑7 小时前
第九章-数字三角形
算法
uesowys7 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
ValhallaCoder7 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
董董灿是个攻城狮7 小时前
AI 视觉连载1:像素
算法
智驱力人工智能8 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
孞㐑¥9 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
月挽清风9 小时前
代码随想录第十五天
数据结构·算法·leetcode
XX風9 小时前
8.1 PFH&&FPFH
图像处理·算法
NEXT069 小时前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法