当前位置: 首页 > news >正文

【力扣100题】48.乘积最大子数组

题目描述

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

测试用例的答案是一个32 位整数。注意,一个只包含一个元素的数组的乘积就是这个元素的值。

示例:

  • 输入:nums = [2,3,-2,4]→ 输出:6(子数组[2,3]有最大乘积 6)
  • 输入:nums = [-2,0,-1]→ 输出:0(结果不能为 2,因为[-2,-1]不是子数组)

解题思路总览

方法思路时间复杂度空间复杂度
动态规划同时维护最大乘积和最小乘积,因为负数会使最小变最大O(n)O(1)
分治递归处理每个区间,考虑奇数个负数和偶数个负数的情况O(n log n)O(log n)
暴力枚举枚举所有子数组计算乘积O(n^2)O(1)

本题采用动态规划方法。


完整代码

classSolution{public:intmaxProduct(vector<int>&nums){intans=INT_MIN,imax=1,imin=1;for(inti=0;i<nums.size();i++){if(nums[i]<0){inttemp=imax;imax=imin;imin=temp;}imax=max(imax*nums[i],nums[i]);imin=min(imin*nums[i],nums[i]);ans=max(ans,imax);}returnans;}};

算法流程图

输入: nums = [2, 3, -2, 4] 初始化: ans = INT_MIN = -∞ imax = 1 imin = 1 i = 0, nums[0] = 2: 2 < 0? 否,不需要交换 imax = max(1*2, 2) = max(2, 2) = 2 imin = min(1*2, 2) = min(2, 2) = 2 ans = max(-∞, 2) = 2 i = 1, nums[1] = 3: 3 < 0? 否,不需要交换 imax = max(2*3, 3) = max(6, 3) = 6 imin = min(2*3, 3) = min(6, 3) = 3 ans = max(2, 6) = 6 i = 2, nums[2] = -2: -2 < 0? 是,交换 imax 和 imin temp = imax = 6 imax = imin = 3 imin = temp = 6 imax = max(3*(-2), -2) = max(-6, -2) = -2 imin = min(6*(-2), -2) = min(-12, -2) = -12 ans = max(6, -2) = 6 i = 3, nums[3] = 4: 4 < 0? 否,不需要交换 imax = max(-2*4, 4) = max(-8, 4) = 4 imin = min(-12*4, 4) = min(-48, 4) = -48 ans = max(6, 4) = 6 最终 ans = 6 输出: 6

逐行解析

intans=INT_MIN,imax=1,imin=1;

含义:

  • ans记录全局最大乘积,初始化为最小整数
  • imax记录以当前位置结尾的连续子数组的最大乘积
  • imin记录以当前位置结尾的连续子数组的最小乘积
  • 初始化为 1 是因为乘积的起始值为 1(单位元)
for(inti=0;i<nums.size();i++)

含义:遍历数组,依次计算以每个位置结尾的子数组的最大乘积。

if(nums[i]<0){inttemp=imax;imax=imin;imin=temp;}

含义:如果当前元素是负数,会将最大乘积和最小乘积互换。因为负数乘以最大数会变成最小数,乘以最小数会变成最大数。

imax=max(imax*nums[i],nums[i]);

含义:更新imax。取「之前累积的最大乘积乘以当前元素」和「重新从当前元素开始」中的较大值。

imin=min(imin*nums[i],nums[i]);

含义:更新imin。取「之前累积的最小乘积乘以当前元素」和「重新从当前元素开始」中的较小值。

ans=max(ans,imax);

含义:更新全局最大乘积。

returnans;

含义:返回所有子数组中的最大乘积。


核心思想:为什么需要同时维护最大和最小乘积?

因为数组中可能存在负数

[2, 3, -2, 4]为例:

  • 当遍历到-2时,之前累积的最大乘积是6
  • 如果继续乘以负数-26 × (-2) = -12,变成很小的数
  • 但如果我们之前累积的是最小乘积呢?2 × 3 × (-2) = -12,再乘以-2就变成24了!

所以,当遇到负数时,最大和最小会互换角色。必须同时记录最大和最小,才能应对各种情况。


复杂度分析

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

面试追问 FAQ

问题答案
为什么初始化imax = imin = 11 是乘法的单位元,方便统一处理「从当前位置重新开始」的情况
为什么不比较imax * nums[i]1 * nums[i]因为nums[i]本身就是imax = 1imax * nums[i]的一种情况
遇到 0 会怎样?0 会让乘积变成 0,同时是子数组的分界线。max(0, imax*0) = 0,会重新从下一个位置开始计算
和最大子数组和(53题)有什么区别?最大子数组和问题可以用贪心,但乘积问题因为负数的存在,必须用动态规划同时维护最大和最小
如何输出具体的子数组?额外记录每个位置的imax是来自之前的累积还是重新开始,最后回溯得到起止位置
进阶:如何求乘积最小子数组?ans = max(ans, imax)改为ans = min(ans, imin)即可

相关题目

题号题目难度核心思路
152乘积最大子数组中等动态规划(最大/最小乘积)
53最大子数组和中等动态规划/贪心
918环形子数组的最大和中等动态规划 + 环形数组
1567乘积为正的最长子数组长度中等动态规划记录正/负乘积长度

总结

要点内容
核心思想同时维护最大乘积和最小乘积,因为负数会使两者互换
状态定义imax[i]= 以第 i 个元素结尾的连续子数组的最大乘积
状态定义imin[i]= 以第 i 个元素结尾的连续子数组的最小乘积
状态转移遇到负数时交换 imax 和 imin,然后imax = max(imax*nums[i], nums[i])
初始化imax = imin = 1ans = INT_MIN
结果返回遍历过程中的最大 ans

http://www.jsqmd.com/news/828960/

相关文章:

  • UVa 281 Rubik‘s Cube
  • 如何自由下载大疆无人机固件:DankDroneDownloader完整使用教程
  • Untrunc常见问题排查:10种错误场景及解决方案
  • 2026昆明婚纱摄影行业黑榜测评榜单 - charlieruizvin
  • SyncedStore架构设计:从CRDT到响应式绑定的完整实现
  • 保姆级教程:在国产Deepin系统上手动安装gfortran依赖,搞定SPECCPU 2017离线部署
  • Markdown文档怎么转Word?2026最实用的MD转Word方法盘点 - AI测评专家
  • Go Imagick 安装全攻略:从零开始配置开发环境 [特殊字符]
  • 角色动作系统完整实现:Boss Room中8种职业技能开发详解
  • RPG游戏开发自动化:基于MCP协议与n8n的RPGMais工作流实践
  • 中英对照版本学英文 | 高中英语学习
  • EB Garamond 12:开源学术排版的革命性字体解决方案
  • Spark数据处理终极利器:10个高效SQL数据源连接器深度解析
  • XCA证书管理器安全最佳实践:10个关键步骤保护您的数字身份
  • 数据工程专用CLI工具的设计与实现:从架构到实践
  • D2DX:3步让暗黑破坏神2在现代PC上焕然一新的终极解决方案
  • 告别吃灰!用OpenWrt把你的正点原子i.MX6ULL开发板变成智能路由器/物联网网关
  • Outfit字体:免费开源的终极几何无衬线字体解决方案,轻松打造品牌视觉一致性 [特殊字符]
  • 从机械盘到NVMe:新旧硬件下的DD镜像仿真参数该怎么选?(UEFI/BIOS避雷指南)
  • 嵌入式开发中OpenSSL的裁剪与集成:从误解到实战
  • Abaqus 2023保姆级教程:手把手教你搞定悬臂梁的动力学仿真(含阻尼设置与结果导出)
  • 手把手教你用U-EC6仿真器给C8051F320烧录第一个LED程序(Keil C51/IAR/Silicon Labs IDE通用)
  • Athas项目架构深度剖析:理解Tauri与React的完美结合
  • 【力扣100题】49.分割等和子集
  • 基于Fabric.js的Web视频编辑器:架构、实现与性能优化
  • 终极Android数学计算神器:nCalc深度解析与使用指南
  • 告别‘悬空’和‘穿模’:Cesium地形上精准放置Entity的5个调试技巧与性能考量
  • PDF怎么转JPG图片?2026年PDF转换方法对比与实测指南 - AI测评专家
  • 怎么用工商登记信息判断一家企业的真实主营业务?一份字段解读手册
  • VASP计算进阶:磁性、HSE06、SOC这些参数到底怎么加?一份参数设置避雷手册