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

LeetCode算法日记 - Day 83: 乘积最大的子数组

目录

1. 乘积最大的子数组

1.1 题目解析

1.2 解法

1.3 代码实现


1. 乘积最大的子数组

https://leetcode.cn/problems/maximum-product-subarray/description/

给你一个整数数组 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 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何子数组的乘积都 保证 是一个 32-位 整数

1.1 题目解析

题目本质
这是一个"动态连续子数组最值"问题,核心是在所有可能的连续子数组中,找出乘积最大的那一个。关键词是"连续"和"乘积最大"。

常规解法
最直观的想法是枚举所有可能的连续子数组:双层循环遍历所有起点和终点,计算每个子数组的乘积,记录最大值。

class Solution {public int maxProduct(int[] nums) {int n = nums.length;int maxProduct = nums[0];  // 至少包含一个元素,初始化为第一个元素// 外层循环:枚举子数组起点for (int i = 0; i < n; i++) {int product = 1;  // 当前子数组的乘积// 内层循环:枚举子数组终点for (int j = i; j < n; j++) {product *= nums[j];  // 累乘当前元素maxProduct = Math.max(maxProduct, product);  // 更新最大值}}return maxProduct;}
}

问题分析
暴力枚举的时间复杂度是 O(n³)(双层循环 + 乘积计算),或优化后 O(n²)。对于 n = 2×10⁴ 的数据规模,这会超时。我们需要 O(n) 的解法。

思路转折
乘法和加法不同的关键点:

  • 加法中,最大子数组和只需关注"要不要继续累加"

  • 乘法中,负数×负数=正数,这意味着当前的最小值(负数)可能在下一步变成最大值

因此传统的单一 DP 状态不够用了。要想高效求解 → 必须同时追踪"最大值"和"最小值" → 引入双状态动态规划。

当遇到负数时,最小值可能翻盘成最大值;当遇到正数时,最大值继续扩大。这样才能捕获所有可能的最大乘积。

1.2 解法

解法

算法思想

使用动态规划,维护两个状态数组:

  • max[i]:以 nums[i-1] 结尾的子数组的最大乘积

  • min[i]:以 nums[i-1] 结尾的子数组的最小乘积

状态转移方程:

max[i] = max(nums[i-1], nums[i-1] × max[i-1], nums[i-1] × min[i-1])min[i] = min(nums[i-1], nums[i-1] × max[i-1], nums[i-1] × min[i-1])result = max(result, max[i])

i)创建大小为 n+1 的

ii)初始化 max[0] = min[0] = 1,作为虚拟起点,方便处理第一个元素

iii)初始化 result = Integer.MIN_VALUE,记录全局最大值

iv)从 i=1 遍历到 i=n,对每个位置:

  • 计算 max[i]:从三个候选值中取最大(单独取当前元素、继承上一个最大值、继承上一个最小值)

  • 计算 min[i]:从三个候选值中取最小(单独取当前元素、继承上一个最大值、继承上一个最小值)

  • 用 max[i] 更新全局最大值 result

v)返回 (int)result

易错点

  • 只维护最大值:会漏掉"最小负数×负数=最大正数"的情况,例如 [-2, -3] 应该返回 6,但只维护最大值会返回 -2

  • result 每次被覆盖:如果写成 result = Math.max(max[i], min[i]),每次循环都会覆盖 result,丢失历史最大值。必须写成 result = Math.max(result, max[i]) 来累积保存所有位置中的最大值

1.3 代码实现

class Solution {public int maxProduct(int[] nums) {int n = nums.length;long[] max = new long[n+1];long[] min = new long[n+1];max[0] = min[0] = 1;long result = Integer.MIN_VALUE;for(int i = 1; i <= n; i++){max[i] = Math.max(nums[i-1], Math.max(nums[i-1]*max[i-1], nums[i-1]*min[i-1]));min[i] = Math.min(nums[i-1], Math.min(nums[i-1]*max[i-1], nums[i-1]*min[i-1]));result = Math.max(result, max[i]);} return (int)result;}
}

复杂度分析

  • 时间复杂度:O(n),只需遍历数组一次,每个位置的计算都是 O(1)

  • 空间复杂度:O(n),使用了两个长度为 n+1 的数组存储中间状态

http://www.dtcms.com/a/528710.html

相关文章:

  • 站长之家的作用什么是优化资源配置
  • FreeRTOS在MCU开发中常用应用
  • AIGC视频生成之Deepseek、百度妙笔组合实战小案例
  • wordpress 付费剧集网站免费建立网站有必要吗
  • ES数据聚合及其java实现
  • 二、模型训练与参数高效微调范式
  • 美的公司网站建设的目的网站设计注意因素
  • 手机环境光自动亮度调节系统完整实现详解
  • 记录一次海思Hi3798MV200-android7.0平台开机卡在第一张图无法进入系统问题分析解决过程
  • 【设计模式笔记03】:里氏代换原则和依赖倒置原则
  • 网站运行环境建设方案南京做网站南京乐识赞
  • [sam2图像分割] 图像编码器 | Hiera FPN Neck
  • 基于 Dify 的 Excel 测试用例自动化脚本生成工作流开发
  • Photoshop - Photoshop 工具栏(16)画笔工具
  • 深圳网站建设信科便宜设计欣赏网
  • CSS简介(本文为个人学习笔记,内容整理自哔哩哔哩UP主【非学者勿扰】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • css之box-sizing属性
  • 【设计模式笔记02】:面向对象设计原则-开闭原则
  • 用于电动汽车的永磁同步电机调速系统建模与仿真(论文+)
  • 校区网站建设网站建设区别
  • 网站建设是什么科目注册企业邮箱免费
  • 长短期记忆网络(LSTM)与门控循环单元(GRU)详解
  • 研究报告:系统排列(Systemic Constellations)的原理、理论体系及文献综述
  • 尚庭公寓学习笔记
  • Unity单例模式基类全解析
  • 餐饮行业做网站的数据ctoc网站有哪些
  • 深圳建设局网站投诉电话淄博网站建设优化公司
  • 久治县网站建设公司东莞人才网最新招聘信息
  • MySQL OCP认证、Oracle OCP认证
  • 深入探讨HarmonyOS中ListItem的滑动操作:从基础实现到高级分布式交互