最大乘积区间问题解析 | 豆包MarsCode AI刷题
题目解析
问题背景
在日常生活中,很多决策都涉及到选择一个最佳的组合或区间,以求得某一指标的最大化。最大乘积区间问题便是这样一个经典的计算问题。我们在这个问题中给定一个数组,目的是选择一个连续的子数组,使得这个子数组的乘积最大。在这个过程中,我们需要考虑到一系列的限制条件,比如数组中可以包含零,如何处理零的影响,以及在多个子数组乘积相同的情况下,如何根据优先级选择最优的区间。
在小R的数组中,元素的取值范围被严格限制在特定的集合中,这决定了对于乘积的计算,只会产生非负整数。这为问题的定义提供了清晰的框架,使得我们能够通过方法论的思考量化问题的解法。
思路分析
1. 乘积计算的基础知识 乘积是一个重要的数学概念,我们在解决乘积相关问题时,通常会使用两个嵌套的循环。外层循环负责选择子数组的起始位置,而内层循环则负责计算当前子数组的乘积。由于在这个问题中,数组的元素来自于一个有限的集合,我们需要在遍历时实时更新当前的乘积,并记录最大乘积及其对应的起始和结束位置。
2. 特殊情况处理 当子数组包含零时,其乘积将为零,这在计算最大乘积时会造成干扰。因此,我们需要在成功计算乘积后检查当前乘积是否为零。如果是零,应该重置乘积并跳过后续的数字;否则,继续计算直到到达数组末尾。
3. 更新最大乘积 每次我们计算出一个乘积后,都需要将其与当前记录的最大乘积进行比较。如果当前乘积更大,更新最大乘积;如果相等,则需要根据题目要求优先选择起始位置更小的区间。如果两个区间的起始位置相同,我们再比较结束位置。
代码详解
接下来,我们通过给出的代码进一步分析实现过程:
def solution(n: int, arr: list[int]) -> list[int]:
max_product = 0
best_start = -1
best_end = -1
# Iterate for all starting points
for i in range(n):
product = 1 # Reset product for each starting index
for j in range(i, n):
product *= arr[j] # Calculate the product for arr[i:j+1]
if product > max_product:
max_product = product
best_start = i + 1 # Convert to 1-based index
best_end = j + 1 # Convert to 1-based index
elif product == max_product:
# If we found same product, check for smaller indices
if (i + 1 < best_start) or (i + 1 == best_start and j + 1 < best_end):
best_start = i + 1
best_end = j + 1
return [best_start, best_end] if max_product > 0 else [-1, -1]
if __name__ == "__main__":
# Test cases
print(solution(5, [1, 2, 4, 0, 8]) == [1, 3]) # Expected output: [1, 3]
print(solution(7, [1, 2, 4, 8, 0, 256, 0]) == [6, 6]) # Expected output: [6, 6]
代码解析
-
初始化参数:
max_product = 0 best_start = -1 best_end = -1这里我们初始化了
max_product用以存储最大乘积,而best_start和best_end用于记录最佳区间的起始和结束位置。 -
外层循环(选择起始位置):
for i in range(n): product = 1这段代码为每个起始位置
i准备乘积计算,并在每次前进到新起始位置时重置乘积。 -
内层循环(计算乘积):
for j in range(i, n): product *= arr[j]在内层循环中,通过不断累乘数组中的元素来获得当前子数组的乘积。
-
更新最大乘积逻辑:
if product > max_product: ... elif product == max_product: ...每当计算出一个新乘积后,我们与
max_product进行比较。如果找到更大乘积,则更新相关变量;如果乘积相同,则根据优先级逻辑更新最佳区间。 -
返回结果:
return [best_start, best_end] if max_product > 0 else [-1, -1]最后根据
max_product是否大于0来返回有效的区间,或者返回[-1, -1]。
示例分析
对题目给出的示例进行详细分析,有助于我们更透彻地理解代码如何运行。
示例1
输入:[1, 2, 4, 0, 8]
- 选择[1, 2, 4],乘积为
1*2*4 = 8,更新最大乘积。 - 当碰到0时,乘积重置,继续遍历。
- 复选区间[4, 0, 8]的乘积为
0,因此继续跳过。 - 最终返回区间为[1, 3]。
示例2
输入:[1, 2, 4, 8, 0, 256, 0]
- 所有子区间的乘积都考虑了,但由于存在
0,有效区间只剩下256,返回[6, 6]。
示例3
输入:[1, 2, 4, 8, 0, 256, 512, 0]
- [6, 7]是两个有效乘积为
256*512的区间,返回最末位置即[6, 7]。
知识总结
-
连续子数组乘积求解:选择连续子数组的问题实际上是动态规划中的一个常见问题。它要求我们不断调用乘积的动态更新,从而找到最优解。
-
特殊值处理:在数组中,零往往是一个潜在的干扰因素,它能迅速改变乘积。随机数组可能使得乘积波动剧烈,因此在设计与实现时需有效处理这些情况。