青训营X豆包MarsCode 技术训练营第一课 97题 | 豆包MarsCode AI刷题

70 阅读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

题目分析与思路整理

问题理解

题目要求从一个长度为 n 的数组中选取一段连续的区间,使得该区间的乘积最大。数组中的元素来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。如果存在多个区间乘积相同的情况,优先选择起始位置 x 更小的区间;如果 x 相同,选择结束位置 y 更小的区间。

数据结构选择

由于我们需要计算连续区间的乘积,并且数组中的元素都是非负整数,因此我们可以直接使用数组来存储这些元素。数组的下标可以直接用来表示区间的起始和结束位置。

算法步骤

  1. 初始化变量

    • max_product:用于存储当前找到的最大乘积。
    • start 和 end:用于存储最大乘积对应的区间起始和结束位置。
  2. 遍历数组

    • 使用外层循环遍历数组的每个元素,将其作为可能区间的起始位置。
    • 对于每个起始位置,使用内层循环遍历从该位置开始的连续区间,计算当前区间的乘积。
  3. 计算乘积

    • 在内层循环中,每次将当前元素乘到当前区间的乘积中。
    • 如果当前元素为0,重置当前区间的乘积,并跳出内层循环,从下一个元素开始新的区间计算。
  4. 更新最大乘积和区间

    • 在每次计算完当前区间的乘积后,比较它与最大乘积,如果当前乘积更大,则更新最大乘积和对应的区间。
    • 如果当前乘积与最大乘积相同,则根据题目要求,优先选择起始位置更小的区间;如果起始位置相同,选择结束位置更小的区间。
  5. 返回结果

    • 最后,返回最大乘积对应的区间起始和结束位置。

代码实现

python

def solution(n: int, arr: list[int]) -> list[int]:

    # 初始化最大乘积和对应的区间

    max_product = -1

    start, end = -1, -1

    

    # 遍历数组

    for i in range(n):

        # 初始化当前区间的乘积

        current_product = 1

        # 遍历从当前位置开始的连续区间

        for j in range(i, n):

            # 计算当前区间的乘积

            current_product *= arr[j]

            

            # 如果当前乘积为0,重置并跳出内层循环

            if current_product == 0:

                break

            

            # 更新最大乘积和对应的区间

            if current_product > max_product:

                max_product = current_product

                start, end = i + 1, j + 1

            elif current_product == max_product:

                # 如果乘积相同,优先选择起始位置更小的区间

                if i + 1 < start or (i + 1 == 

                start and j + 1 < end):

                    start, end = i + 1, j + 1

    

    return [start, end]

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. 问题分解与抽象

在解决这个问题时,首先需要将问题分解为几个关键步骤:初始化变量、遍历数组、计算乘积、更新最大乘积和区间、返回结果。这种分解问题的能力是编程中非常重要的,它帮助我们将复杂的问题简化为一系列可管理的步骤。

2. 边界条件的处理

在编程中,边界条件的处理往往是最容易出错的地方。在这个问题中,我们需要特别注意数组中可能出现的0元素。0会使得任何区间的乘积变为0,因此我们需要在内层循环中及时检测并处理这种情况。这种对特殊情况的细致处理是确保程序正确性的关键。

3. 优化与性能考虑

虽然这个问题的时间复杂度是O(n^2),但对于给定的数组长度(n最大为1000),这个复杂度是可以接受的。然而,在实际应用中,我们可能需要考虑更高效的算法,例如动态规划或滑动窗口等方法来优化性能。

4. 代码的可读性与维护性

在编写代码时,保持代码的可读性和维护性是非常重要的。通过合理的变量命名、清晰的注释以及模块化的代码结构,我们可以使代码更易于理解和维护。例如,在这个问题中,我们将计算乘积和更新最大乘积的逻辑分开,使得代码更加清晰。

5. 测试与验证

在编写代码后,进行充分的测试是确保代码正确性的关键。通过编写多个测试用例,我们可以验证代码在不同情况下的表现,并及时发现和修复潜在的问题。在这个问题中,我们通过测试用例验证了代码在不同输入下的正确性。

6. 算法思维的培养

通过解决这类问题,我们可以培养算法思维,学会如何分析问题、选择合适的数据结构和算法、以及如何优化代码性能。这种思维方式不仅在编程中有用,在其他领域也能帮助我们更好地解决问题。

总结

通过解决这个问题,我们不仅学会了如何处理连续区间的乘积问题,还掌握了一些编程中的基本技巧,如问题分解、边界条件处理、代码优化、可读性维护以及测试验证。这些技能对于成为一名优秀的程序员至关重要。