第97题 小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.数组特性:数组元素均来自一个特定的集合,这意味着数组中不会出现除这些元素外的其他数值。 2.乘积计算:由于数组中可能包含0,因此任何包含0的区间乘积都将为0,除非该区间仅包含一个非零元素。 3.区间选择:在存在多个乘积相同的区间时,需按照起始位置x(若x相同则按y)更小的原则来选择。 4.索引转换:题目要求输出基于1的索引,而Python等编程语言通常使用基于0的索引,因此需要进行相应的转换。
关键点
-
乘积的特性:
- 由于数组中的元素都是正数或0,乘积的结果要么是正数,要么是0。
- 如果区间中包含0,那么该区间的乘积为0。
-
区间的选择:
- 如果存在多个区间乘积相同的情况,优先选择
x更小的区间;如果x相同,选择y更小的区间。
- 如果存在多个区间乘积相同的情况,优先选择
解题思路
-
遍历所有可能的区间:
- 我们可以通过两层循环来遍历所有可能的区间
[i, j],其中i是区间的起始位置,j是区间的结束位置。 - 计算每个区间的乘积,并记录最大乘积及其对应的区间。
- 我们可以通过两层循环来遍历所有可能的区间
-
处理0的情况:
- 如果区间中包含0,那么该区间的乘积为0。我们可以选择忽略这些区间,或者在比较时特别处理。
-
优化:
- 由于数组中的元素都是正数或0,我们可以利用这个特性来优化计算。例如,当遇到0时,可以直接跳过后续的计算。
def solution(n, arr):max_product = float('-inf') start_idx, end_idx = 1, 1 # 初始化起始与结束位置为1(基于1的索引) # 遍历所有可能的区间 for i in range(n): product = 1 for j in range(i, n): product *= arr[j] # 计算当前区间的乘积(注意:这里arr是基于0的索引) # 由于arr中的元素都是正数(除了0),因此我们可以在遇到0时立即停止内层循环 # 但为了保持与题目要求的一致性(即使乘积为0也要考虑),我们仍然计算整个区间的乘积 # 不过,在后续的比较中,我们可以忽略那些乘积为0且长度不是1的区间 # 更新最大乘积及其对应区间 if product > max_product: max_product = product start_idx = i + 1 # 转换为基于1的索引 end_idx = j + 1 # 转换为基于1的索引 # 如果乘积相等,则根据题目要求不更新或更新为x更小的区间(这里已经隐含在比较中了) # 由于题目中可能存在多个0导致某些区间乘积为0,我们需要特别处理这种情况 # 如果最大乘积仍然是负无穷(即没有找到有效的非零乘积区间),则默认选择第一个元素作为区间 # 但根据题目要求和给出的样例,这种情况似乎不会发生,因为至少有一个非零元素存在 # 因此,下面的处理逻辑主要是为了代码的健壮性而添加的 if max_product == float('-inf'): return [1, 1] # 默认返回第一个元素作为区间(这是一个保守的选择,实际情况可能需要根据题目具体要求来调整) return [start_idx, end_idx]测试样例
print(find_max_product_interval(5, [1, 2, 4, 0, 8])) # 输出: [1, 3]
print(find_max_product_interval(7, [1, 2, 4, 8, 0, 256, 0])) # 输出: [6, 6]
print(find_max_product_interval(8, [1, 2, 4, 8, 0, 256, 512, 0])) # 输出: [6, 7]