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

LeetCode 热题 100_乘积最大子数组(88_152_中等_C++)(动态规划)

LeetCode 热题 100_乘积最大子数组(88_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-位 整数

题解:

解题思路:

思路一(暴力破解法(双重循环)):

1、计算所有的子数组的乘积,记录其中乘积的最大值,每个子数组的范围为 left~right(left 和 right 代表数组下标)。
2、复杂度分析:
① 时间复杂度:O(n2),n代表数组中元素的个数,使用了双重循环。
② 空间复杂度:O(1)

思路二(动态规划):

1、因数组中的元素既有正数又有负数,这样我们需要分情况讨论(由于负数的存在,当前最小乘积在遇到负数时可能会转为最大乘积,从而有可能影响最终的最大值。)。此解法通过动态维护当前最大乘积最小乘积来有效地解决问题。

四种情况如下
假设有nums=[a,b],假设a!=0,b!=0。

  1. a>0,b>0 乘积最大为 a*b。
  2. a>0,b<0 乘积最大为 a。
  3. a<0,b>0 乘积最大为 b。
  4. a<0,b<0 乘积最大为 a*b。

:nums = [2,3,-2,4]
之前的最大乘积为:pre_max,之前的最小乘积为:pre_min
当前的最大乘积为:cur_max,当前的最小乘积为:cur_min

① i=0 ,初始化 pre_max = pre_min = cur_max = cur_min = nums[ 0 ] = 2 。
② i=1 ,cur_max = max{nums[ 1 ],nums[ 1 ] × pre_min,nums[ 1 ] × pre_max } =6, cur_min = min{nums[ 1 ],nums[ 1 ] × pre_min,nums[ 1 ] × pre_max} = 3。
③ i=2,cur_max = max{nums[ 2 ],nums[ 2 ] × pre_min,nums[ 2 ] × pre_max } = -2,cur_min = min{nums[ 2 ],nums[ 2 ] × pre_min,nums[ 2 ] × pre_max} = -12。
④ i=3,cur_max = max{nums[ 3 ],nums[ 3 ] × pre_min,nums[ 3 ] × pre_max } = 4,cur_min = min{nums[ 3 ],nums[ 3 ] × pre_min,nums[ 3 ] × pre_max} = -48。
在此过程中记录最大的 cur_max=6 最为乘积最大子数组。

3、复杂度分析
① 时间复杂度:O(n),n代表数组中元素的个数。因只遍历一遍数组。
② 空间复杂度:O(1)。

代码实现

代码实现(思路一(暴力破解法)):
class Solution1 {
public:// 函数:maxProduct,计算给定数组中子数组的最大乘积int maxProduct(vector<int> &nums) {// 初始化答案为最小的整数值,后续将通过比较更新答案int ans = INT_MIN;// 外层循环:从每个可能的子数组起始位置开始for (int left = 0; left < nums.size(); left++) {// 初始化当前子数组的乘积为 1int cur_product = 1;// 内层循环:从 left 位置开始向右遍历,计算当前子数组的乘积for (int right = left; right < nums.size(); right++) {// 更新当前子数组的乘积cur_product *= nums[right];// 更新答案为当前子数组的乘积和之前答案的较大值ans = max(cur_product, ans);}}// 返回找到的最大乘积return ans;}
};
代码实现(思路二(哈希表)):
class Solution2 {
public:// 函数:maxProduct,计算给定数组中子数组的最大乘积int maxProduct(vector<int> &nums) {// 初始化答案为数组的第一个元素long long ans = nums[0];// 初始化当前最大乘积和最小乘积,均为数组的第一个元素long long cur_max = nums[0], cur_min = nums[0];// 从第二个元素开始遍历数组for (int i = 1; i < nums.size(); i++) {// 保存前一次的最大乘积和最小乘积long long pre_max = cur_max, pre_min = cur_min;// 计算当前最大乘积:// 1. nums[i] 本身// 2. nums[i] * 前一次的最大乘积// 3. nums[i] * 前一次的最小乘积cur_max = max(max((long long)nums[i], nums[i] * pre_max), (long long)nums[i] * pre_min);// 计算当前最小乘积:// 1. nums[i] 本身// 2. nums[i] * 前一次的最大乘积// 3. nums[i] * 前一次的最小乘积cur_min = min(min((long long)nums[i], nums[i] * pre_max), (long long)nums[i] * pre_min);// 更新答案为当前最大乘积和之前答案的较大值ans = max(ans, cur_max);}// 返回找到的最大乘积return ans;}
};
以思路二为例进行调试
#include<iostream>
#include<vector>
using namespace std;class Solution2 {
public:// 函数:maxProduct,计算给定数组中子数组的最大乘积int maxProduct(vector<int> &nums) {// 初始化答案为数组的第一个元素long long ans = nums[0];// 初始化当前最大乘积和最小乘积,均为数组的第一个元素long long cur_max = nums[0], cur_min = nums[0];// 从第二个元素开始遍历数组for (int i = 1; i < nums.size(); i++) {// 保存前一次的最大乘积和最小乘积long long pre_max = cur_max, pre_min = cur_min;// 计算当前最大乘积:// 1. nums[i] 本身// 2. nums[i] * 前一次的最大乘积// 3. nums[i] * 前一次的最小乘积cur_max = max(max((long long)nums[i], nums[i] * pre_max), (long long)nums[i] * pre_min);// 计算当前最小乘积:// 1. nums[i] 本身// 2. nums[i] * 前一次的最大乘积// 3. nums[i] * 前一次的最小乘积cur_min = min(min((long long)nums[i], nums[i] * pre_max), (long long)nums[i] * pre_min);// 更新答案为当前最大乘积和之前答案的较大值ans = max(ans, cur_max);}// 返回找到的最大乘积return ans;}
};int main(int argc, char const *argv[])
{vector<int> nums={1,0,-5,2,3,-8,-9};Solution2 s;cout<<s.maxProduct(nums);return 0;
}

LeetCode 热题 100_乘积最大子数组(88_152)原题链接
欢迎大家和我沟通交流(✿◠‿◠)

相关文章:

  • rpcrt4!COMMON_AddressManager函数分析之和全局变量rpcrt4!AddressList的关系
  • 纯FPGA实现AD9361控制的思路和实现 UART实现AXI_MASTER
  • 《AI大模型应知应会100篇》第26篇:Chain-of-Thought:引导大模型进行步骤推理
  • 常见设计模式
  • Github 2025-04-19Rust开源项目日报 Top10
  • 清华《数据挖掘算法与应用》K-means聚类算法
  • Redis--主从复制
  • 记录一次项目中使用pdf预览过程以及遇到问题以及如何解决
  • 【Bluedroid】蓝牙存储模块配置管理:启动、读写、加密与保存流程解析
  • Unity webgl 获取图片或视频数据
  • UI键盘操作
  • 机器学习+深度学习
  • 开发基于python的商品推荐系统,前端框架和后端框架的选择比较
  • 青少年编程与数学 02-016 Python数据结构与算法 30课题、数据压缩算法
  • 基于DeepSeek与Excel的动态图表构建:技术融合与实践应用
  • 平均池化(Average Pooling)
  • 【绘制图像轮廓】图像处理(OpenCV) -part7
  • Fastdata极数:全球AR/VR行业发展趋势报告2025
  • spring-batch批处理框架(1)
  • 面向新一代扩展现实(XR)应用的物联网框架
  • “站在亚洲实现整体振兴的新起点上”——习近平主席对越南、马来西亚、柬埔寨进行国事访问纪实
  • 科普|军团菌肺炎:春末夏初的隐形健康威胁
  • 杨国荣丨阐释学的内涵与意义——张江《阐释学五辨》序
  • 新闻1+1丨全球首场人机共跑马拉松,有何看点?
  • 世卫成员国就《大流行病协议》达成一致,首次演练应对气候诱发的病毒危机
  • 江西农商联合银行正式挂牌开业