LeetCode152. 乘积最大子数组(2024秋季每日一题 2)

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

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

示例 1:

复制代码
输入: nums = [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

示例 2:

复制代码
输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

提示:

1 < = n u m s . l e n g t h < = 2 ∗ 1 0 4 1 <= nums.length <= 2 * 10^4 1<=nums.length<=2∗104
− 10 < = n u m s i < = 10 -10 <= numsi <= 10 −10<=numsi<=10
n u m s nums nums 的任何子数组的乘积都 保证 是一个 32 32 32-位 整数


方法一:暴力: O ( N 2 ) O(N^2) O(N2)

能过的样例数: 187 / 190 187/190 187/190

思路:第一层循环枚举子数组长度,第二层循环枚举子数组区间左边的索引,并且维护一个滑动窗口,用于记录窗口内的乘积值。

cpp 复制代码
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = -20;
        for(int len = 1; len <= nums.size(); len++){
            int x = 1, l = -1;
            for(int j = 0; j <= len - 1; j++){
                if(x == 0) x = nums[j];
                else x *= nums[j];
                if(nums[j] == 0) l = j;
            }
            res = max(res, x);
            for(int i = 1; i + len - 1 < nums.size(); i++){
                if(x == 0) x = nums[i + len - 1];
                else {
                    if(nums[i + len - 1] == 0) l = i + len - 1;
                    if(nums[i-1] != 0 && i > l){
                        x = x / nums[i-1] * nums[i + len - 1];
                    }else{
                        x = x * nums[i + len - 1];
                    }
                }
                res = max(res, x);
            }
        }
        return res;
    }
};

方法二:DP: O ( N ) O(N) O(N)

思路:维护三个数,res、imax、imin

  • 遍历数组时维护当前子数组的最大值、最小值
  • 当遇到负数时,最大值,最小值交换
  • 当遇到0时,imax,imin 重置,在子数组内重新计算

注意:这里的子数组指的是 以 0 为分割的子数组

i m a x = m a x ( n u m s i , i m a x ∗ n u m s i ) imax = max(numsi, imax * numsi) imax=max(numsi,imax∗numsi)
i m i n = m i n ( n u m s i , i m i n ∗ n u m s i ) imin = min(numsi, imin * numsi) imin=min(numsi,imin∗numsi)

当乘给 负数 时,imin 与 imax 交换(最大,最小值交换)

cpp 复制代码
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = -20, imin = 1, imax = 1;
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] < 0) swap(imin, imax);
            imax = max(imax * nums[i], nums[i]);
            imin = min(imin * nums[i], nums[i]);

            res = max(res, imax);
        }
        return res;
    }
};
相关推荐
先吃饱再说11 小时前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰13 小时前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术15 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六18 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术19 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize19 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考1 天前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营1 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队2 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法