问题解析与解决思路
问题描述
- 你需要在一个数组中找到一个连续子数组,使其乘积最大。
- 数组可能包含
0和负数:0会将任何乘积归零,因此需要将子数组从0之后重新开始计算。- 负数会使乘积变号,因此可能需要考虑从右到左的反向计算,以找到更大的正数乘积。
解决方案的核心思路
-
正向遍历:从左到右计算最大乘积
- 遍历数组时,每次计算从某个位置到当前位置的连续乘积。
- 如果乘积被
0打断,将乘积重置为1,并从下一个位置重新开始计算。 - 如果当前乘积超过已记录的最大乘积,更新最大乘积并记录对应的子数组起止位置。
-
反向遍历:从右到左计算最大乘积
- 为了应对负数的翻转问题,补充一次从右到左的遍历。
- 和正向遍历类似,遇到
0时,重置乘积,并从下一个位置开始重新计算。 - 如果从右到左的计算得到的最大乘积更大,则更新结果。
-
索引选择
- 如果多个子数组的最大乘积相等,按照以下规则选择:
- 优先选择起点索引(x)更小的子数组。
- 如果起点相等,则选择终点索引(y)更小的子数组。
- 如果多个子数组的最大乘积相等,按照以下规则选择:
关键点的文字解释
-
为什么需要双向遍历?
- 在正向遍历时,如果子数组中有偶数个负数,乘积会变为正数并可能是最大值;但如果子数组以负数结尾,可能遗漏更大的结果。
- 反向遍历可以从子数组的末尾开始重新计算,弥补正向遍历的不足,确保不会遗漏由负数翻转产生的更大乘积。
-
如何处理 0?
- 当遍历到数组中的
0时,乘积会被重置为 0,因此需要将乘积重置为 1,并从下一个位置重新开始。 - 这种方法可以分割连续子数组,跳过无意义的
0。
- 当遍历到数组中的
-
如何确保结果的正确性?
- 正向和反向遍历分别考虑了所有可能的子数组组合。
- 每次更新最大乘积时,都会记录对应的起止索引,最终可以返回符合条件的子数组范围。
-
结果返回为什么需要 1 基索引?
- 题目要求结果以从 1 开始的索引返回,因此需要将内部计算的 0 基索引转换为 1 基索引。
总结
- 正向遍历:找到从左到右的最大连续子数组乘积。
- 反向遍历:补充计算从右到左的最大连续子数组乘积,确保负数翻转的情况不会遗漏。
- 特殊处理 0:遇到
0时重置乘积并重新开始计算。 - 索引记录:始终跟踪子数组的起止位置,确保符合题目要求的返回格式和选择规则。