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

71 阅读4分钟

题目解析

这个问题的核心是计算数组中每个元素的 L(i)R(i),然后通过这两个值计算 MAX(i),并找出最大值。为了帮助大家更好地理解和解决这个问题,我将从以下几个方面进行详细分析:

  1. L(i) 和 R(i) 的定义与理解

    • L(i)  是满足条件 a[j] > a[i] 且 j < i 中的最大 j。如果不存在这样的 j,则 L(i) = 0
    • R(i)  是满足条件 a[k] > a[i] 且 k > i 中的最小 k。如果不存在这样的 k,则 R(i) = 0
  2. MAX(i) 的定义

    • MAX(i) = L(i) * R(i),我们要求的是所有 i 值中的 MAX(i) 的最大值。

思路分析

根据题目要求,我们需要遍历数组来为每个位置计算 L(i)R(i),然后计算每个 MAX(i)。这个问题的解决方案可以分成以下几个步骤:

  1. 计算 L(i)

    • 对于每个元素 a[i],我们需要从左到右检查其前面的所有元素,找到最大的 j,使得 a[j] > a[i]。这个过程是线性扫描。
  2. 计算 R(i)

    • 对于每个元素 a[i],我们需要从右到左检查其后面的所有元素,找到最小的 k,使得 a[k] > a[i]。这个过程也是线性扫描。
  3. 计算 MAX(i)

    • 对于每个位置 i,我们有了 L(i) 和 R(i),可以直接计算出 MAX(i)
  4. 找出最大值

    • 最后,遍历所有 i,找出 MAX(i) 的最大值。

优化策略

直接遍历每个 i,计算 L(i)R(i) 的时间复杂度是 O(n^2),这个时间复杂度对于较大的 n 来说会比较慢。为了优化这个过程,我们可以考虑使用栈来提高效率,具体方法是利用单调栈来加速 L(i)R(i) 的计算。

代码实现

pythonCopy Code
def solution(n, array):
    # 初始化 L 和 R 数组
    L = [0] * n
    R = [0] * n
    
    # 计算 L(i)
    stack = []
    for i in range(n):
        while stack and array[stack[-1]] <= array[i]:
            stack.pop()
        if stack:
            L[i] = stack[-1] + 1  # 1-based index
        stack.append(i)
    
    # 计算 R(i)
    stack = []
    for i in range(n-1, -1, -1):
        while stack and array[stack[-1]] <= array[i]:
            stack.pop()
        if stack:
            R[i] = stack[-1] + 1  # 1-based index
        stack.append(i)
    
    # 计算 MAX(i) 并找出最大值
    max_value = 0
    for i in range(n):
        max_value = max(max_value, L[i] * R[i])
    
    return max_value

# 测试用例
print(solution(5, [5, 4, 3, 4, 5]))  # 输出: 8
print(solution(6, [2, 1, 4, 3, 6, 5]))  # 输出: 15
print(solution(7, [1, 2, 3, 4, 5, 6, 7]))  # 输出: 0

代码详解

  1. 计算 L(i)

    • 我们使用一个栈来帮助寻找每个 i 左侧的第一个比 a[i] 大的元素。栈内存储的是元素的索引,栈顶始终保持的是最近的比当前元素大的元素的索引。
    • 如果栈顶的元素小于等于当前元素,我们就弹出栈顶,直到栈顶的元素大于当前元素。如果栈不为空,栈顶元素对应的就是我们需要的 L(i)
  2. 计算 R(i)

    • 同样地,我们使用一个栈来帮助寻找每个 i 右侧的第一个比 a[i] 大的元素,过程与计算 L(i) 类似,只不过我们是从右向左扫描。
  3. 计算 MAX(i)

    • 通过前两步的结果,我们可以直接计算出每个 i 的 MAX(i) = L(i) * R(i),然后找到最大的 MAX(i)

测试结果

  • 对于输入 array = [5, 4, 3, 4, 5],输出应为 8。
  • 对于输入 array = [2, 1, 4, 3, 6, 5],输出应为 15。
  • 对于输入 array = [1, 2, 3, 4, 5, 6, 7],输出应为 0。

总结

  1. 通过栈的方式优化了计算 L(i) 和 R(i) 的过程,避免了暴力的双重循环。
  2. 时间复杂度降低到 O(n),适合处理大规模数据。
  3. 通过合理的数据结构和算法优化,提高了问题解决的效率。

学习计划与总结

  1. 刷题的策略:可以将问题划分成几个小部分,每部分逐步实现,逐步优化。先理解问题本质,再考虑时间复杂度,最后考虑如何优化。
  2. 学习栈与单调栈的应用:栈是非常重要的数据结构,可以帮助我们高效地解决一些搜索问题。单调栈的应用场景非常广泛,特别是当需要寻找某个元素左侧或右侧第一个满足条件的元素时。

希望通过这篇笔记,大家能够对栈的使用有更深入的理解,并能够在今后的算法学习中更好地应用这些知识点。