简单解析最大乘积区间问题 | 豆包MarsCode AI 刷题

142 阅读3分钟

一、题目分析

题目:给定一个长度为 n 的数组,数组元素来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。从中选取一段连续区间,使得该区间内的元素乘积最大,并输出该区间的起始位置 x 和结束位置 y(从1开始计数)。

思考过程:

目标是在数组中找到一段连续的区间,使得该区间内元素的乘积最大。 题目在双指针的分类里,考虑使用双指针做题。

需要注意的点有:

数组元素为0时: 0 会将乘积变为 0,所以需要在遇到 0 时跳过或者重新开始计算新的子数组。

有多个相同乘积的区间时: 优先选择起始位置较小的区间,如果起始位置相同,则选择结束位置较小的区间。

边界条件为: 如果数组中全是 0,需要返回 [-1, -1] 表示没有有效的区间。 题目限定数组长度 n 大于 0

可以得出以下这个基本思路:

(1)需要遍历数组,并在每个起始点开始寻找最大乘积的连续子数组。

(2)使用嵌套循环来遍历所有可能的连续子数组。

(3)当找到一个新的最大乘积时,更新最大乘积和对应的起始位置 start 和结束位置 end

(4)注意处理数组中包含 0 的情况,因为 0 会使得乘积变为零,并且分割连续的子数组。

举个例子

假设有一个数组 [1, 2, 4, 0, 8]

[1, 2, 4] 可以得到乘积 1 * 2 * 4 = 8

0 则是一个分割符,使得我们重新开始计算新的区间

8 单独一项,其乘积为 8

在这个例子中,最大乘积为 8,出现在 [1, 2, 4][8] 两个区间中,但 [1, 2, 4] 的起始位置较小,所以选择 [1, 2, 4]

二、解答题目

步骤解析:

第一步:初始化

  • max_product = float('-inf') 用于存储当前找到的最大乘积值,初始值为负无穷。

  • start 和 end 用于存储最大乘积区间的起始和结束位置,初始值为-1

第二步:创建外层循环

用于遍历数组的每个元素:

    for i in range(n):
        if arr[i] == 0:
            continue 
  • 外层循环从数组的第一个元素开始遍历。

  • 如果当前元素是 0,则跳过这个元素,继续下一个,因为0会将乘积变为0。

第三步:创建内层循环

用于计算从当前位置开始的所有连续子数组的乘积:

p = 1  # 初始化乘积,p为product的简写
for j in range(i, n):
    if arr[j] == 0:
        break  # 遇到0跳出内循环
        p *= arr[j]  # 计算子数组乘积
  • 初始化 p 为 1,用于存储当前子数组的乘积。
  • 内层循环从当前 i 开始,继续向右扩展子数组。
  • 如果遇到 0,跳出内层循环,开始下一个 i 的处理。
  • 每次更新子数组乘积 p

第四步:比较并更新最大乘积和它的区间

if p > max_product:
    max_product = p
    start = i
    end = j
elif p == max_p:
    if i < start or (i == start and j < end):
        start = i
        end = j
  • 如果当前乘积 p 大于 max_product,则更新 max_product 以及 start 和 end
  • 如果当前乘积 p 等于 max_product,则选择起始位置较小或结束位置较小的区间。

第五步:处理边界情况

if start == -1 or end == -1:
    return [-1, -1]

如果没有找到有效的区间(即 start 和 end 仍为-1),返回 [-1, -1]

最后返回结果

[start + 1, end + 1] 返回结果时,将 start 和 end 加1,因为题目要求数组的起始位置为 1

这道简单题就做完了。