欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 动态规划-乘积最大子数组

动态规划-乘积最大子数组

2024/10/24 23:14:58 来源:https://blog.csdn.net/2302_80190174/article/details/141865332  浏览:    关键词:动态规划-乘积最大子数组

题目描述

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组 (该子数组中至少包含一个数字),并返回该子数组所对应的乘积。 测试用例的答案是一个 32-位 整数。

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

解题思路

使用了两个动态规划数组 f 和 g 来分别跟踪到当前位置为止,乘积最大和最小的子数组乘积。这是基于以下观察:

  1. 最大乘积(f 数组):在遍历数组时,对于每个位置 i,最大乘积要么是当前元素 nums[i] 本身(如果前面的元素都是负数或者乘积小于当前元素),要么是前面位置的最大乘积 f[i-1] 乘以当前元素 nums[i](如果前面的乘积是正数或者0)。但是,当遇到负数时,我们需要考虑前一个位置的最小乘积 g[i-1] 乘以当前负数 nums[i] 是否能产生新的最大乘积(因为负数乘以负数会变成正数)。

  2. 最小乘积(g 数组):与最大乘积类似,最小乘积的更新也考虑了当前元素、前一个位置的最小乘积乘以当前元素,以及前一个位置的最大乘积乘以当前元素(当当前元素为负数时)。这是因为,负数乘以正数(前一个位置的最大乘积)会得到一个更小的负数,这可能是新的最小乘积。

上述的动态规划思路与此前的最大子数组和一题相似。

在遍历过程中,f 和 g 数组被逐步构建,并且我们始终保持 f 数组中的最大值作为当前已知的最大乘积。遍历完成后,f 数组中的最大值即为所求的最大乘积子数组的乘积。

代码示例

class Solution {
public:int maxProduct(vector<int>& nums) {int n = nums.size();vector<int> f(n, 0); // 乘积最大的子数组vector<int> g(n, 0); // 乘积最小的子数组f[0] = g[0] = nums[0];for (int i = 1; i < n; i++) {if (nums[i] > 0) {f[i] = max(nums[i] * f[i - 1], nums[i]);g[i] = min(nums[i], nums[i] * g[i - 1]);} else {f[i] = max(nums[i], nums[i] * g[i - 1]);g[i] = min(nums[i], nums[i] * f[i - 1]);}}int ret = f[0];for (int i = 1; i < n; i++) {ret = max(ret, f[i]);}return ret;}
};

 

以下是代码的主要步骤:

  • 初始化 f[0] 和 g[0] 为 nums[0],因为第一个元素既是最大乘积也是最小乘积的起点。
  • 遍历数组 nums,从第二个元素开始:
    • 如果当前元素 nums[i] 是正数,则最大乘积 f[i] 可以是 nums[i] 或者 nums[i] * f[i-1](取决于哪个更大),最小乘积 g[i] 可以是 nums[i] 或者 nums[i] * g[i-1](取决于哪个更小)。
    • 如果当前元素 nums[i] 是负数,则最大乘积 f[i] 可以是 nums[i] 或者 nums[i] * g[i-1](因为负数乘以负数变正数,可能成为新的最大乘积),最小乘积 g[i] 可以是 nums[i] 或者 nums[i] * f[i-1](因为负数乘以正数变得更小)。
  • 遍历完成后,f 数组中的最大值即为所求的最大乘积。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com