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

70 阅读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]`
解释:最大乘积为arr[0]乘到arr[2]即1*2*4=8

测试样例2

输入:`n = 7, arr = [1, 2, 4, 8, 0, 256, 0]`  
输出:`[6, 6]`
解释:最大乘积为arr[5]即256

问题分析

我们把题目分成一条一条的来分析:

  1. “数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

    这句话告诉我们数组元素不是0就是1就是比1大的正整数,扩展连续区间时,如果最右端的元素非1非0,则乘积增大;如果最右端的元素为1,则乘积不变;如果最右端的元素为0,则前功尽弃,乘积变为0,因此我们要跳过0。

  2. “如果存在多个区间乘积相同的情况,优先选择 x 更小的区间;如果 x 相同,选择 y 更小的区间。”

    这句话告诉我们除了0以外,要格外注意处理1的情况。例如[1,128,0,0,16,16,512,1,0,8]这样一个区间,可以看到如果不考虑1的边界情况,我们会取到[16,16,512,1]这样一个子区间作为答案,因为显然它的成绩最大,但是一个需要注意的地方是由于末尾乘过1,这个最大乘积在乘1前就已经出现过,即子区间[16,16,512]的乘积也是最大,而题目要求我们成绩相同的情况下,且x也相同的情况下,选择y更小的区间。

    因此我们每更新一个最大乘积时,需要格外数一下末尾1的个数num_of_1,右下标righ减去1的个数num_of_1即可。

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

    返回答案时,下标值均+1即可。

参考代码

def solution(n, data):
    # Edit your code here
    left = -1    #初始化值
    right = -1
    max_product = -1
    index = 0
    while index < n:
        while index < n and data[index] == 0:    #跳过0
            index += 1
        tmp = index
        product = 1
        while index < n and data[index] != 0:    #连乘,遇到0时停止
            product *= data[index]
            index += 1
        if product > max_product:    #如果乘积大于最大乘积,更新值
            max_product = product
            left = tmp
            i = index - 1
            count_of_1 = 0
            while i >= 0 and data[i] == 1:    #计算区间末尾1的个数,right向前倒退1的个数即可。
                count_of_1 += 1
                i -= 1
            right = index - 1 - count_of_1
    return [left + 1, right + 1]