最大乘积区间问题 | 豆包MarsCode AI刷题

42 阅读3分钟

最大乘积区间问题

一、问题重现

问题描述

小R手上有一个长度为 n 的数组 (n > 0),数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想从这个数组中选取一段连续的区间,得到可能的最大乘积。

你需要帮助小R找到最大乘积的区间,并输出这个区间的起始位置 x 和结束位置 y (x ≤ y)。如果存在多个区间乘积相同的情况,优先选择 x 更小的区间;如果 x 相同,选择 y 更小的区间。

注意:数组的起始位置为 1,结束位置为 n


测试样例

样例1:

输入:n = 5, arr = [1, 2, 4, 0, 8]
输出:[1, 3]

样例2:

输入:n = 7, arr = [1, 2, 4, 8, 0, 256, 0]
输出:[6, 6]

样例3:

输入:n = 8, arr = [1, 2, 4, 8, 0, 256, 512, 0]
输出:[6, 7]

二、解题思路

  1. 问题理解:

    • 你需要在一个数组中找到一个连续的子数组,使得该子数组的乘积最大。
    • 数组中的元素来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
    • 如果存在多个乘积相同的子数组,优先选择起始位置 x 更小的子数组;如果 x 相同,选择结束位置 y 更小的子数组。
  2. 数据结构选择:

    • 使用两个指针 i 和 j 来表示当前考虑的子数组的起始和结束位置。
    • 使用一个变量 pro 来记录当前子数组的乘积。
    • 使用 max_product 来记录当前找到的最大乘积。
    • 使用 begin 和 end 来记录最大乘积子数组的起始和结束位置。
  3. 算法步骤:

    • 初始化 max_product 为0,begin 和 end 为0,i 和 j 为0,pro 为1。
    • 使用一个循环遍历数组,每次将当前元素乘到 pro 中。
    • 如果当前元素为0且不是最后一个元素,则跳过该零值并重新开始计算乘积。
    • 如果当前乘积 pro 大于 max_product,则更新 max_product 和对应的区间 begin 和 end
    • 返回包含起始和结束位置的列表,位置从1开始计数。

算法实现

  1. 变量初始化:

    • max_product 初始化为0,用于记录最大乘积。
    • begin 和 end 初始化为0,用于记录最大乘积子数组的起始和结束位置。
    • i 和 j 初始化为0,用于表示当前考虑的子数组的起始和结束位置。
    • pro 初始化为1,用于记录当前子数组的乘积。
  2. 循环遍历:

    • 使用 while 循环遍历数组,每次将当前元素 data[j] 乘到 pro 中。
    • 如果当前元素 data[j] 为0且不是最后一个元素,则跳过该零值并重新开始计算乘积,即将 i 更新为 j + 1,并将 pro 重置为1。
    • 如果当前乘积 pro 大于 max_product,则更新 max_product 和对应的区间 begin 和 end
    • j 每次循环递增1。
  3. 返回结果:

    • 返回包含起始和结束位置的列表,位置从1开始计数。

三、代码实现

def solution(n, data):
    max_product = 0
    begin = 0
    end = 0
    i = 0
    j = 0
    pro = 1
    while j < n:
        pro *= data[j]
        if data[j] == 0 and j < n - 1:
            i = j + 1
            pro = 1
        if pro > max_product:
            max_product = pro
            begin = i
            end = j
        j += 1
    
    return [begin + 1, end + 1]

四、算法复杂度

时间复杂度

  1. 外层循环O(n)

  2. 内层操作O(1)

  3. 总时间复杂度O(n)

空间复杂度

O(1)