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

101 阅读4分钟

首先我们附加上原题:

小 R 手上有一个长度为 n 的数组 (n > e), 数组中的元素分别来自集合[0,1,2,4, 8 16,32,64,128,256,512,1024 ]。小R 想从这个数组中选取一段连续的区间,得到可能的最大乘积。你需要帮助小 R 找到最大乘积的区间,并输出这个区间的起始位置 x 和结束位置 y(x <= y) 。如果存在多个区间乘积相同的情况,优先选择 x 更小的区间;如果 x 相同,选择 y 更小的区间。注意:数组的起始位置为 1 ,结束位置为n

在详细解析这个问题时,我们可以从以下几个方面展开:

1. 理解问题

我们面对的任务是在一个数组中找到一个连续的子数组(区间),使得这个子数组的乘积最大化。问题要求我们在找到最大乘积的同时,如果有多段区间能达到相同的最大乘积,我们应优先选择起始位置 x 更小的区间。如果起始位置 x 也相同,那么我们选择结束位置 y 更小的区间。这意味着,如果存在多个解决方案,我们应该优先考虑在数组中位置最靠前的那个,而在同样靠前的多个解决方案中,我们应该选择结束位置最靠前的那个。

2. 处理特殊情况

一个特别的情况是我们需要注意的:如果数组中的所有元素都是 0,那么最大乘积显然是 0。在这种情况下,由于任何包含 0 的区间的乘积都会是 0,所以任意选择一个单个 0 作为区间都是满足条件的。这个特殊情况的处理避免了在计算过程中产生不必要的复杂性。

3. 遍历数组

为了找到最大乘积的区间,我们可以使用两个指针 start 和 end 来表示当前正在考虑的子数组。这两个指针会随着我们遍历数组而移动,从而动态地改变当前考虑的区间。遍历过程中,我们需要计算当前由 start 和 end 指针所界定的区间的乘积,并与之前记录的最大乘积进行比较。如果当前乘积更大,则更新最大乘积及其对应的区间。

4. 处理乘积为 0 的情况

在遍历数组时,我们会遇到数组元素为 0 的情况。由于 0 会使任何数的乘积变为 0,所以当遇到 0 时,我们知道当前区间的乘积已经达到了 0,再继续扩展这个区间(即移动 end 指针)已经没有意义,因为再乘以任何数(包括负数和非零正数)都不会使乘积变得更大。因此,一旦遇到 0,我们应该考虑结束当前区间的计算,并将 start 指针移动到 end 指针的下一个位置,从而开始一个新的区间的计算。

5. 更新最大乘积和区间

在遍历过程中,我们始终保持对最大乘积及其对应区间的记录。每当发现一个新的乘积大于当前记录的最大乘积时,我们就更新这个记录,同时记录下新的最大乘积对应的区间(即 start 和 end 的位置)。如果在遍历结束后,没有发现比初始记录(可能是负数或者非常小的正数,取决于数组的具体情况)更大的乘积,那么我们依然保持最初的记录。不过,在大多数情况下,我们会在遍历过程中至少找到一个正乘积(除非数组全是 0),从而更新最大乘积和区间。

通过上述步骤,我们能够有效地找到一个数组中具有最大乘积的连续区间,并且在有多个解决方案时,根据问题的要求选择最优的解。

`

def solution(n, data):
    max_product = -1
    best_start = -1
    best_end = -1

    for start in range(n):
        current_product = 1
        for end in range(start, n):
            current_product *= data[end]
            if current_product == 0:
                break
        
            if current_product > max_product or (current_product == max_product and (start < best_start or (start == best_start and end < best_end))):
                max_product = current_product
                best_start = start
                best_end = end
    return [best_start + 1, best_end + 1]


if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 4, 0, 8]) == [1, 3])
    print(solution(7, [1, 2, 4, 8, 0, 256, 0]) == [6, 6])

`

关键步骤解释:

初始化:max_product 用于存储最大乘积,best_start 和 best_end 用于存储最大乘积对应的区间。

双层循环:外层循环遍历区间的起始位置 start,内层循环遍历区间的结束位置 end。

计算乘积:在内层循环中,计算从 start 到 end 的乘积。

更新最大乘积和区间:如果当前乘积大于 max_product,或者乘积相同但区间更优,则更新 max_product 和对应的区间。

返回结果:注意区间的起始位置和结束位置是从 1 开始计数的,因此返回时需要加 1。