力扣152:乘积最大子数组

力扣152:乘积最大子数组

题目

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

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

思路

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

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

但是现在我不用这种方法了我们想一想其他的思路,在经过上面的分析时发没发现一个情况那就是子数组的两边是不可能都有负数的因为只要乘上这两个负数整个的乘积是肯定会变大的啊,还有就是子数组的任意一侧是不可能有正数的,一样的情况乘上这个正数整个的乘积是会变大的而我们求得就是最大乘积。所以这就导致了我们最后的子数组的两端一定是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,当numsi,pre,bck。可能会有疑惑为什么要带上numsi呢,我直接举例子大家就知道了当数组为-2,0,-1时,最大乘积不就是0吗。所以带上numsi是因为子数组有可能只有一个元素。

代码

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;
    }
};
相关推荐
月华路1 小时前
G1 新生代对象晋升老年代:实现机制与 GC 日志
java·jvm·算法
万法若空1 小时前
排列组合恒等式
c++·算法
Nil2082 小时前
leetcode 105从前序和中序遍历序列构造二叉树
算法·leetcode·职场和发展
一直C2 小时前
【数据结构】哈希表+算法复杂度与经典排序查找(C语言)
java·linux·开发语言·数据结构·算法·ubuntu·散列表
淡海水2 小时前
04-02-哈希-Dictionary-TKey-TValue-上-核心数据结构
数据结构·算法·c#·哈希算法·编译·字典·dictionary
戴西软件2 小时前
国内有哪些数据轻量化格式转换软件?
数据库·算法·安全·信息可视化·自动化·rpa
老洋葱Mr_Onion2 小时前
【C++】CSP-J初赛模拟卷七错题整理(作者自用)
c++·算法·深度优先
Nil2082 小时前
leetcode 114二叉树展开为链表
leetcode·链表·深度优先
土星云SaturnCloud2 小时前
Real-ESRGAN超分辨率算法原理与边缘侧部署实践
服务器·算法·ai·边缘计算·real-esrgan
cz07103 小时前
hot100_搜索二维矩阵 II
算法·leetcode