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

LeetCode-热题100: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 * 104
  • -10 <= nums[i] <= 10
  • nums 的任何前缀或后缀的乘积都 保证 是一个 32-位 整数

(动态规划)代码及注释

func maxProduct(nums []int) int {// 初始化最大乘积、最小乘积和结果为数组的第一个元素maxProduct, minProduct, result := nums[0], nums[0], nums[0]// 遍历数组,从第二个元素开始for i := 1; i < len(nums); i++ {// 如果当前数字是负数,交换最大乘积和最小乘积if nums[i] < 0 {maxProduct, minProduct = minProduct, maxProduct}// 计算当前位置的最大乘积和最小乘积maxProduct = max(nums[i], maxProduct * nums[i])minProduct = min(nums[i], minProduct * nums[i])// 更新结果,取当前的最大乘积和之前的结果中的较大值result = max(result, maxProduct)}// 返回最大乘积return result
}// 辅助函数,返回两个整数中的较大值
func max(a, b int) int {if a > b {return a}return b
}// 辅助函数,返回两个整数中的较小值
func min(a, b int) int {if a < b {return a}return b
}

代码解释

1.使用 maxValminVal

在这个问题中,乘积的最大值或最小值可能会受到负数的影响。因此,我们需要维护两个变量:maxValminVal

  • maxVal: 维护以当前元素为结尾的子数组的最大乘积。
  • minVal: 维护以当前元素为结尾的子数组的最小乘积。
2.当遇到负数时

当遇到负数时,最大值和最小值会互相交换,因为负数乘以一个负数会变成正数,可能会变得更大。

3.更新 maxValminVal
  • maxVal = max(nums[i], maxVal * nums[i]): 对于当前元素 nums[i],我们比较它和 maxVal * nums[i] 的乘积,取其中的最大值。

  • minVal = min(nums[i], minVal * nums[i]): 同样地,我们比较当前元素 nums[i]minVal * nums[i] 的乘积,取其中的最小值。

4.更新结果
  • 每次更新 maxVal 后,我们都需要更新全局结果 res

(暴力)代码及注释

func maxProduct(nums []int) int {// 初始化结果为最小整数值res := math.MinInt32// 外部循环遍历数组for i := 0; i < len(nums); i++ {// 初始化临时乘积为1tmp := 1// 内部循环计算从 i 开始到数组末尾的连续子数组的乘积for j := i; j < len(nums); j++ {tmp *= nums[j]// 更新结果res = max(tmp, res)}}// 返回结果return res
}// 辅助函数,返回两个整数中的较大值
func max(a, b int) int {if a > b {return a}return b
}

代码解释

1.使用 res 初始化为 math.MinInt32
  • 初始化 resmath.MinInt32 是为了保证结果能够正确地被更新。如果数组 nums 中的所有元素都是非正数,那么最大乘积应该是 math.MinInt32
2.使用双重循环计算乘积
  • 外部循环从数组的第一个元素开始,内部循环从外部循环的当前位置开始,计算从当前位置到数组末尾的连续子数组的乘积。
3.更新 res
  • 在计算每一个连续子数组的乘积时,我们都会更新 res,确保它始终保存着乘积的最大值。

优点和缺点

优点:
  • 这个方法非常直观,通过双重循环穷举了所有可能的连续子数组。
缺点:
  • 时间复杂度较高,为 (O(n^2)),其中 (n) 是数组的长度。

  • 空间复杂度为 (O(1))。

这个方法虽然直观,但由于时间复杂度较高,对于大规模的数据可能会导致性能问题。

相关文章:

  • 自动驾驶中的传感器融合算法:卡尔曼滤波器和扩展卡尔曼滤波器
  • 无人机飞行知识
  • Vue的模块化开发初探
  • 十四款大型语言模型在《街头霸王III》中一决雌雄
  • Gradle系列(五)-常用的gradle命令
  • 牛顿:Archetype AI 的开创性模型,实时解读真实世界的新宠儿
  • 蓝桥杯 经验技巧篇
  • Http Download
  • UE4_动画基础_ 使用分层动画(Using Layered Animations)
  • 探索算力(云计算、人工智能、边缘计算等):数字时代的引擎
  • 【机器学习】一文掌握机器学习十大分类算法(下)。
  • 基于Spring Boot 3 + Spring Security6 + JWT + Redis实现登录、token身份认证
  • 无人机概述
  • 【Python】无法将“pip”项识别为 cmdlet、函数、脚本文件或可运行程序的名称解决方案
  • YOLOv5全网独家改进: 卷积魔改 | 变形条状卷积,魔改DCNv3二次创新
  • ES6指北【2】—— 箭头函数
  • 《Java编程思想》读书笔记-对象导论
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 【面试系列】之二:关于js原型
  • AngularJS指令开发(1)——参数详解
  • angular学习第一篇-----环境搭建
  • java中的hashCode
  • uva 10370 Above Average
  • 大主子表关联的性能优化方法
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 经典排序算法及其 Java 实现
  • 警报:线上事故之CountDownLatch的威力
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 让你的分享飞起来——极光推出社会化分享组件
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 再谈express与koa的对比
  • 最近的计划
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • MPAndroidChart 教程:Y轴 YAxis
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (03)光刻——半导体电路的绘制
  • (06)Hive——正则表达式
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (多级缓存)多级缓存
  • (二)linux使用docker容器运行mysql
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (四)JPA - JQPL 实现增删改查
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)原始图像数据和PDF中的图像数据
  • . NET自动找可写目录
  • .NET Core 2.1路线图
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • ?php echo ?,?php echo Hello world!;?