不能只用最大值相乘,因为负负得正、零清空乘积、乘积增长快,需同时维护当前最大积和最小积,通过滚动更新maxsofar和minsofar实现o(n)时间复杂度。

为什么不能只用最大值相乘?
找积最大的子数组和找和最大的子数组逻辑完全不同,因为负负得正、零会清空乘积、且乘积增长极快。单纯记录当前最大值会漏掉「前面有两个负数,中间夹着一个正数」这种关键组合。比如 [-2, 3, -4],整个数组积是 24,但若按贪心只保留正数或跳过负数,就得不到结果。
- 负数出现奇数次时,最大积可能来自去掉最左边或最右边那个负数的后缀/前缀
- 遇到
0必须重置状态,因为任何包含0的子数组积都是0 - 必须同时维护「当前最大积」和「当前最小积」:最小积可能是负数,下一个负数来时它就翻成最大积
用两个变量滚动更新 maxSoFar 和 minSoFar
这是最常用也最稳妥的做法,时间 O(n),空间 O(1),不依赖额外容器。
- 每次遍历新元素
nums[i],基于上一轮的maxSoFar和minSoFar计算三个候选值:nums[i]、maxSoFar <em> nums[i]</em>、minSoFar nums[i] - 新的
maxSoFar取三者最大,新的minSoFar取三者最小 - 全局答案在每次更新后取
maxSoFar的历史最大值
int maxProduct(vector<int>& nums) {
if (nums.empty()) return 0;
int maxSoFar = nums[0], minSoFar = nums[0], result = nums[0];
for (int i = 1; i <p>注意:必须用临时变量保存旧的 <code>maxSoFar</code>,否则 <code>minSoFar</code> 更新时用的是已覆盖的新值,逻辑就错了。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<h3>遇到 <code>0</code> 时要不要清空?</h3>
<p>要,但不是“清空”,而是重置为 <code>nums[i]</code> 本身。因为子数组必须连续,一旦断在 <code>0</code>,新子数组只能从 <code>0</code> 或其后开始。</p>
<ul>
<li>当 <code>nums[i] == 0</code> 时,<code>maxSoFar</code> 和 <code>minSoFar</code> 都设为 <code>0</code>
</li>
<li>下一轮如果 <code>nums[i+1]</code> 是负数,<code>minSoFar</code> 就能立刻捕获它,为后续翻盘留可能</li>
<li>不要跳过 <code>0</code> 或设为 <code>1</code> —— 那会破坏连续性,也混淆了“以当前位置结尾”的语义</li>
</ul>
<h3>边界和特殊输入怎么处理?<ul>
<li>空数组:按题意通常返回 <code>0</code> 或抛异常,代码里先判空</li>
<li>单元素:直接返回该元素,<code>maxSoFar</code>/<code>minSoFar</code> 初始化即覆盖</li>
<li>全负数组(如 <code>[-2,-3,-4]</code>):最大积是 <code>-2</code>(长度为 1),算法自然支持,无需特判</li>
<li>大数溢出:C++ 默认不检查,如果题目要求防溢出,需改用 <code>long long</code> 中间计算,但最终返回仍为 <code>int</code>;实际面试中一般假设不溢出</li>
</ul>
</h3>
<p>真正容易被忽略的是:这个算法求的是「连续子数组」,不是子序列;且它不记录起止位置——如果需要输出具体子数组,得额外维护索引变量,每次更新 <code>maxSoFar</code> 时同步更新左右边界。</p></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










