LeetCode Hot100(71/100)——152. 乘积最大子数组

LeetCode 152. 乘积最大子数组【c++/java详细题解】 目录1、题目2、思路:3、c++代码4、java代码 1、题目 给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。 示例 2: 输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 2、思路: (动态规划) O(n)O(n)O(n) 给你一个整数数组 nums ,让我们找出数组中乘积 阅读详情

题目链接

LeetCode 152. 乘积最大子数组

题目说明

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 2 × 10⁴
  • -10 <= nums[i] <= 10
  • nums 的任何前缀或后缀的乘积都保证是一个 32 位整数

问题分析

这道题的核心难点在于处理负数。与求和不同,乘积运算有以下特点:

  1. 负数乘以负数会变成正数
  2. 遇到 0 会使乘积归零
  3. 当前的最小值(负数)可能在下一步变成最大值

正数

负数

零

否

是

遍历数组

当前元素

最大值变更大
最小值变更小

最大值和最小值互换

重置为0

更新全局最大值

是否遍历完

返回结果

解法一:动态规划(双状态维护)

原理讲解

这是最优雅的解法。核心思想是同时维护两个状态:

  • maxProduct:以当前位置结尾的子数组的最大乘积
  • minProduct:以当前位置结尾的子数组的最小乘积

为什么要维护最小值?因为当遇到负数时,之前的最小值(可能是很大的负数)乘以当前负数会变成很大的正数。

状态转移方程:

maxProduct = max(nums[i], maxProduct * nums[i], minProduct * nums[i])
minProduct = min(nums[i], maxProduct * nums[i], minProduct * nums[i])

当前元素

计算三个候选值

nums_i

maxProduct × nums_i

minProduct × nums_i

取最大值作为新maxProduct

取最小值作为新minProduct

Java实现

class Solution {
    public int maxProduct(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        
        // 初始化最大值、最小值和结果
        int maxProduct = nums[0];
        int minProduct = nums[0];
        int result = nums[0];
        
        // 从第二个元素开始遍历
        for (int i = 1; i < nums.length; i++) {
            int current = nums[i];
            
            // 保存当前的maxProduct,因为计算minProduct时需要用到
            int tempMax = maxProduct;
            
            // 更新最大乘积:当前元素、当前元素×最大乘积、当前元素×最小乘积
            maxProduct = Math.max(current, Math.max(tempMax * current, minProduct * current));
            
            // 更新最小乘积
            minProduct = Math.min(current, Math.min(tempMax * current, minProduct * current));
            
            // 更新全局最大值
            result = Math.max(result, maxProduct);
        }
        
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(n),只需遍历数组一次
  • 空间复杂度:O(1),只使用了常数个变量

解法二:动态规划(数组存储)

原理讲解

这个解法与解法一思路相同,但使用数组来存储每个位置的最大值和最小值,更直观地展示动态规划的过程。

dpMax数组

存储以i结尾的最大乘积

dpMin数组

存储以i结尾的最小乘积

状态转移

更新全局最大值

Java实现

class Solution {
    public int maxProduct(int[] nums) {
        int n = nums.length;
        
        // dpMax[i] 表示以 nums[i] 结尾的子数组的最大乘积
        int[] dpMax = new int[n];
        // dpMin[i] 表示以 nums[i] 结尾的子数组的最小乘积
        int[] dpMin = new int[n];
        
        // 初始化
        dpMax[0] = nums[0];
        dpMin[0] = nums[0];
        int result = nums[0];
        
        // 状态转移
        for (int i = 1; i < n; i++) {
            dpMax[i] = Math.max(nums[i], Math.max(dpMax[i-1] * nums[i], dpMin[i-1] * nums[i]));
            dpMin[i] = Math.min(nums[i], Math.min(dpMax[i-1] * nums[i], dpMin[i-1] * nums[i]));
            result = Math.max(result, dpMax[i]);
        }
        
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(n),遍历数组一次
  • 空间复杂度:O(n),需要两个长度为 n 的数组

解法三:双向遍历

原理讲解

这是一个巧妙的解法。观察发现,如果数组中没有 0,那么最大乘积子数组要么是整个数组,要么是去掉前面若干元素,要么是去掉后面若干元素。

核心思想:

  1. 从左到右遍历一次,计算累积乘积
  2. 从右到左遍历一次,计算累积乘积
  3. 遇到 0 时重置乘积为 1
  4. 记录过程中的最大值
右向左遍历 数组 左向右遍历 右向左遍历 数组 左向右遍历 遇到0重置为1 遇到0重置为1 返回两次遍历的最大值 计算前缀乘积 更新最大值 计算后缀乘积 更新最大值

Java实现

class Solution {
    public int maxProduct(int[] nums) {
        int n = nums.length;
        int result = Integer.MIN_VALUE;
        
        // 从左到右遍历
        int product = 1;
        for (int i = 0; i < n; i++) {
            product *= nums[i];
            result = Math.max(result, product);
            // 遇到0重置
            if (product == 0) {
                product = 1;
            }
        }
        
        // 从右到左遍历
        product = 1;
        for (int i = n - 1; i >= 0; i--) {
            product *= nums[i];
            result = Math.max(result, product);
            // 遇到0重置
            if (product == 0) {
                product = 1;
            }
        }
        
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(n),需要遍历数组两次
  • 空间复杂度:O(1),只使用常数个变量

测试用例演示

让我们用示例 [2,3,-2,4] 来演示解法一的执行过程:

初始: max=2, min=2, result=2

i=1, num=3

max=max_6,6,6_=6
min=min_3,6,6_=3
result=6

i=2, num=-2

max=max_-2,-12,-6_=-2
min=min_-2,-12,-6_=-12
result=6

i=3, num=4

max=max_4,-8,-48_=4
min=min_4,-8,-48_=-48
result=6

返回 6

解法对比分析

解法时间复杂度空间复杂度实现难度代码可读性推荐指数
动态规划(双状态维护)O(n)O(1)中等高⭐⭐⭐⭐⭐
动态规划(数组存储)O(n)O(n)简单很高⭐⭐⭐⭐
双向遍历O(n)O(1)较难中等⭐⭐⭐

推荐使用解法一(动态规划-双状态维护),因为它在时间和空间上都达到了最优,代码简洁且易于理解。解法二适合初学者理解动态规划的思想,解法三则是一个巧妙的技巧,适合面试时展示思维能力。

ABAP Cloud 开发教程的文章目录 本教程涵盖 ABAP 云端 Client 处理、多租户架构、ABAP Cloud开发、动态编程优化、SQL语法改进等技术主题。最新版本1.0.0(更新至2025-12-12),包含197篇文章,重点文章包括《ABAP Client Handling与隔离机制》《ABAP Platform 2021泛型编程》《SAP BTP ABAP多租户应用开发》等,为开发者提供从基础到进阶的实战指南。 阅读详情

相关推荐

burpsuite抓取ios数据包

1:首先在burpsuite中设置 添加proxy listeners 2:电脑开热点,手机连接,把代理设为电脑的ip和代理的端口 3:在Safari浏览器中打开网址http://burp下载证书 4:打开设置->通用->描述文件与设备管理 5:设置->通用->关于本机->证书信任设置 之后就可以正常抓包了 ...

weixin_45682070的博客 2065

力扣(LeetCode)152. 乘积最大子数组(C++)

【墨染】序列dp之乘积最大子数组,朴素dp || 滚动数组优化

墨染 1250

鼎捷T100—二次开发:客制化联络对象维护作业 aooi350

鼎捷T100二次开发,客制化

weixin_52342654的博客 1132

leetcode----152.乘积最大子数组(动态规划,两个状态数组)

152.乘积最大子数组 问题:给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 我首先使用暴力枚举做的,后面实在没有思路,参考官方题解,自己总结一下。 思路:定义dp[i]为以第 i个元素结尾的最大子数组的乘积。若给定数组nums中的所有元素都非负,则有dp[i] = max{dp[i-1]*a_i, dp[i]},但是由于给定数组中有负数,所以该状态转移方程不对,以[2,3,-2,-2]为例,dp数组应该为[2,6,-2,4],而

Thomasc的博客 554

法兰克仿真软件FANUC CNC Guide v25.0 安装教程及中文设置

下载地址在文末。我们公司用新到一批FANUC 系统的设备,为方便使用就装了一个 FANUC 数控系统仿真软件FANUC CNC Guide v25.0 ,还是最新版不是市面上流传的老版本。模拟学习一下。

hakesashou的博客 1万+

因果推断综述-A Survey on Causal Inference

最近读到一篇讲述很全面的综述文献-《A Survey on Causal Inference》,对于接触因果推断不久的同学而言是特别详细的介绍和科普。文献很长,我会分成几部分介绍。 目录 摘要 第一部分:简介 第二部分:因果推断基础知识 第三部分:基于三种假设的因果推断方法 第四部分:实验 第五部分:应用 摘要 几十年来,因果推理是一个跨许多领域的关键研究主题,如统计、计算机科学、教育、公共政策和经济学。与随机对照试验相比,研究方向由于可用数据量大且预算要求低,如今,从观测数据..

海边凝望的博客 3182

【LeetCode-中等】152. 乘积最大子数组(详解)

java:动态规划

丨康有为丨的博客 964

✨从零搭建 Ubuntu22.04 + Python3.11 + PyTorch2.5.1 GPU Docker 镜像并上传 Docker Hub

构建一个带 GPU 支持的深度学习开发镜像;使用 PyTorch 2.5.1(CUDA 12.4)环境;发布并托管 Docker 镜像至 Docker Hub;验证 GPU 环境正常运行!🎉 这将极大提升你的项目部署效率,尤其是在多人协作或跨平台部署场景中。

用大模型重构生活:猫奴程序员的AI智能日常记录 1576

Leetcode刷题(第152题)——乘积最大子数组

一、题目 给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中 至少包含一个数字),并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位 整数。 子数组 是数组的连续子序列。 二、示例 输入: nums = [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。 输入: nums = [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 三、思路 本题我们需要保存三个变量,一个是最大值,一个是当前的值,

weixin_47450807的博客 1041

【爬虫实战】Instagram博主图片爬取:模拟登录+滚动加载,轻松抓取高清美图

在当今社交媒体时代,Instagram作为全球最受欢迎的图片分享平台之一,汇聚了无数优质博主的海量精美图片。对于数据爱好者、营销分析师、AI训练数据收集者来说,如何高效、稳定地爬取Instagram博主的图片,成为了一项极具实用价值的技术挑战。然而,Instagram的反爬机制日益严格,传统的静态页面请求已经无法满足需求。本文将带你从零开始,使用2024-2025年最新技术栈,实现模拟登录、滚动加载、高清图片下载的全流程爬虫。✅ 全流程代码可直接运行✅ 模拟手机端请求绕过反爬。

2201_76125261的博客 596

Pytorch入门实战(7):基于BERT实现文本隐喻二分类(Kaggle入门题目)

Bert入门实战,文本二分类问题

iioSnail的博客 4055

【Leetcode hot 100】152.乘积最大子数组

摘要 本文探讨了LeetCode 152题"乘积最大子数组"的两种解法。该问题的核心在于处理乘积运算中负数反转和零截断的特殊情况。解法一采用动态规划,通过维护当前最大/最小乘积变量,在O(n)时间、O(1)空间内求解。解法二利用左右遍历法,通过两次扫描处理奇数个负数的情况。两种方法均能高效解决问题,其中动态规划更具通用性,可推广到类似需要维护正负极值的问题场景。

专注Java和MySQL领域知识分享 613

Playwright实战:打造绕过全维度前端反爬的无头浏览器爬虫(2026实战版)

Playwright绕过前端反爬的核心是模拟真实:真实的设备指纹、真实的行为轨迹、真实的网络请求;2025年前端反爬的核心检测维度是设备指纹+行为轨迹+网络请求,三者缺一不可;实战中需重点关注WebGL/Canvas指纹模拟、行为随机性、请求头完整性,这是绕过反爬的关键;性能优化需以“不触发反爬”为前提,优先选择浏览器复用、资源拦截,而非无限制并发。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 2094

【leetcode hot 100 152】乘积最大子数组

i。

longii11的博客 598

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

力扣(leetcode)hot 100普通数组看这一篇就够了

这期带来的是关于力扣 hot 100当中关于普通数组这一节的内容。保证看了的人都能够学会

yyyCode的博客 2363

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

力扣hot100_普通数组_python版本

【代码】力扣hot100_普通数组_python版本。

Y1n的博客 3878

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

(LeetCode-Hot100)152. 乘积最大子数组

本文介绍了LeetCode 148题"排序链表"的两种解法:自顶向下归并排序和自底向上归并排序。自顶向下方法通过递归将链表二分后合并,时间复杂度O(n log n),但空间复杂度O(log n)。自底向上方法通过迭代实现,满足O(n log n)时间复杂度和O(1)空间复杂度的进阶要求。文中提供了Java和Go语言的具体实现代码,并比较了不同方法的优缺点,指出其他方法如转数组排序和快速排序的局限性。

小飞的博客 483

leetcode hot 100-152. 乘积最大子数组

152. 乘积最大子数组 题目描述: 给你一个整数数组 nums,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。 示例 2: 输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组 思路...

Lucky小黄人的博客 286

LeetCode热题 HOT100:排序链表、乘积最大子数组、最小栈

LeetCode热题 HOT100:排序链表、乘积最大子数组、最小栈

weixin_51405802的博客 812

最详细,最简单的力扣(leetcode)hot 100 动态规划(下)篇讲解

最详细的关于力扣(leetcode)hot 100的动态规划的下半部分的内容。保证看了的朋友都能学会

yyyCode的博客 1873

力扣刷题Hot100之普通数组

比如7个数k=3 由[0,1,2,3,4,5,6]->[6,5,4,3,2,1,0]->[4,5,6,0,1,2,3]比较(x+nums[i],nums[i])记录当前最大和,并且比较(x,max)记录数组最大和,遍历得到结果。如果先(0,2)(3,6)数组就是[2,1,0,6,5,4,3]->[3,4,5,6,0,1,2]其实反推很好想出来,假如每次循环一次就返回到原点那循环到k-1就结束,最小公约数为k。利用动态规划解决,遍历数组,用变量x记录前一位的最大和,max为数组最大和。

weixin_74567525的博客 1746

力扣hot100

【代码】力扣hot100。

qq_59768361的博客 1400

hot100 乘积最大子数组(152)

遗忘temp状态隔离:直接写fMax = ...;导致fMin误用了已更新的fMax,这是初学者最常犯的逻辑溃败。初始化盲目设定为 0:如果将fMax和fMin初始赋值为 0,当数组全为负数(如)时,0 会作为污染因子参与Math.max比较,导致输出结果错误地变为 0(正确答案应为 -2 或 24)。整型乘法溢出(Integer Overflow):题目保证了子数组乘积在 32 位整型范围内,但在实际业务中(如浮点数或大整数乘积),连续乘法极易突破上限。工程实现中应视情况切换为long型或安全校验。

2603_96126046的博客 195

Leecode hot100 - 152. 乘积最大子数组

给你一个整数数组nums,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个整数。6子数组 [2,3] 有最大乘积 6。0结果不能为 2, 因为 [-2,-1] 不是子数组。

2301_79601111的博客 375

动态规划刷题笔记(一):乘积最大子数组,最长有效括号

ps:笔记和代码按本人理解整理,重思路

学习记录 772

【Hot100】LeetCode—152. 乘积最大子数组

【代码】【Hot100】LeetCode—152. 乘积最大子数组。

weixin_44382896的博客 573
上一篇: LeetCode Hot100(70/100)—— 322. 零钱兑换
下一篇: wsl2下Docker拉取镜像很慢的最快解决办法
TracyCoder123
博客等级 码龄8年 1万+粉丝 226原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TracyCoder123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值