青训营X豆包MarsCode 技术训练营:最大乘积区间问题Python3题解 | 豆包MarsCode AI 刷题

107 阅读5分钟

问题描述

小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,乘积的结果可能会非常大,因此我们需要考虑如何处理这些情况。
  2. 数据结构选择:我们可以使用两个指针来表示当前考虑的区间,并使用一个变量来记录当前区间的乘积。
  3. 算法步骤
    • 初始化两个指针 startend,以及一个变量 max_product 来记录最大乘积。
    • 遍历数组,计算从 startend 的乘积。
    • 如果乘积为0,则跳过这个区间,并将 start 移动到 end 的下一个位置。
    • 如果乘积大于 max_product,则更新 max_product 和区间的起始和结束位置。
    • 如果乘积等于 max_product,则比较当前区间的起始和结束位置,选择更小的区间。

Python3代码(通过Marscode测试)

def solution(n, data):
    max_product = 0
    best_start = -1
    best_end = -1
    
    # 遍历数组,尝试所有可能的区间
    for start in range(n):
        current_product = 1
        for end in range(start, n):
            # 计算当前区间的乘积
            current_product *= data[end]
            
            # 如果乘积为0,跳过这个区间
            if current_product == 0:
                break
            
            # 如果当前乘积大于最大乘积,更新最大乘积和区间
            if current_product > max_product:
                max_product = current_product
                best_start = start
                best_end = end
            # 如果乘积相等,选择更小的区间
            elif current_product == max_product:
                if start < best_start or (start == best_start and end < best_end):
                    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])

关键步骤解释

  1. 初始化max_product 用于记录最大乘积,best_startbest_end 用于记录最大乘积区间的起始和结束位置。
  2. 遍历数组:使用两个嵌套的循环来遍历所有可能的区间。
  3. 计算乘积:在内部循环中,计算从 startend 的乘积。
  4. 更新最大乘积:如果当前乘积大于 max_product,则更新 max_product 和区间的起始和结束位置。如果乘积相等,则选择更小的区间。
  5. 返回结果:返回区间的起始和结束位置,注意数组的起始位置为1,因此需要将 best_startbest_end 加1。 这道题目使用了暴力枚举算法来解决。具体来说,它通过遍历所有可能的子区间来找到最大乘积区间。

算法复杂度

  • 时间复杂度:由于使用了两个嵌套的循环,时间复杂度为 O(n^2),其中 n 是数组的长度。
  • 空间复杂度:空间复杂度为 O(1),因为我们只使用了常数个额外的变量。

豆包MarsCode AI 刷题体验

对于题库中的大部分题目,豆包MarsCode AI 都可以一次性生成正确的思路和代码(代码可以一次性通过Marscode测试)。AI提出的思路和代码示例对于刚刚入门算法的初学者来说意义非凡。初学者可以参考这些思路和代码进行自主学习,亦可通过参考这些代码和思路提升学习效率。

目前,豆包MarsCode AI 刷题只支持java和Python,对于编辑区代码的分析功能还有待提升,对于生成的代码,豆包MarsCode AI 不能第一时间给出算法的时间复杂度和空间复杂度(一上来直接点思路或者代码提示),这可能会一定程度上阻碍学习者发掘算法优化的指标和方向。如果豆包MarsCode AI 可以解决以上问题,那么它将成为一款有里程碑意义的编程学习工具。为广大算法学习者带来福音。

在日常学习和科研中,我主要使用Python语言,所以“豆包MarsCode AI 刷题只支持java和Python”这一局限对我影响不大。最希望系统可以尽快支持C/C++,这对于算法党来说是一个福音(编程语言的优势哈哈哈)。

这一次是一道简单的暴力枚举问题,没有太多算法思想,通过暴力枚举所有可能的子区间,我们可以找到最大乘积区间。虽然这种方法的时间复杂度较高,但对于较小的数组(例如 n <= 1000),这种方法是可行的。