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

43 阅读4分钟

问题描述

小S最近在分析一个数组 h1,h2,...,hNh1​,h2​,...,hN​,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。

对于 kk 个相邻的元素,我们定义其矩形的最大面积为:

R(k)=k×min(h[i],h[i+1],...,h[i+k−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kk,R(k)R(k) 的最大值。


测试样例

样例1:

输入:n = 5, array = [1, 2, 3, 4, 5]
输出:9

样例2:

输入:n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9

样例3:

输入:n = 4, array = [4, 4, 4, 4]
输出:16

题目解析

思路

这道题的核心是通过滑动窗口和单调栈求解最大矩形面积:

  1. 定义矩形面积:选取任意 kkk 个相邻元素,矩形面积 R(k)R(k)R(k) 是这些元素的最小值乘以 kkk。

  2. 优化计算过程:如果直接对每个 kkk 计算最小值,会导致复杂度为 O(n2)O(n^2)O(n2)。因此,引入单调栈优化到 O(n)O(n)O(n)。

  3. 单调栈思想

    • 左右扩展每个元素,找到第一个小于它的位置,从而确定以该元素为高度的矩形宽度。
    • 使用单调递增栈快速查找左右边界。

图解

假设数组为 [2,1,5,6,2,3][2, 1, 5, 6, 2, 3][2,1,5,6,2,3],我们以高度 h[i]h[i]h[i] 为中心计算影响范围:

  1. 构建 left 数组:每个柱子左侧第一个小于它的下标。

  2. 构建 right 数组:每个柱子右侧第一个小于它的下标。

  3. 计算矩形面积:

    • 宽度为 right[i]−left[i]−1\text{right}[i] - \text{left}[i] - 1right[i]−left[i]−1,高度为 h[i]h[i]h[i]。
    • 更新最大值。

代码详解

代码分为三部分:

  1. 初始化:创建 leftright 数组,辅助栈 stack

  2. 构建边界

    • 遍历数组,利用单调递增栈分别计算左右边界。
  3. 计算最大矩形面积

    • 遍历每个元素,利用宽度和高度计算面积并更新最大值。

代码如下:

python
复制代码
def solution(n, array):
    max_area = 0
    left = [0] * n
    right = [0] * n

    # 构建左边界
    stack = []
    for i in range(n):
        while stack and array[stack[-1]] >= array[i]:
            stack.pop()
        left[i] = stack[-1] if stack else -1
        stack.append(i)

    # 构建右边界
    stack = []
    for i in range(n - 1, -1, -1):
        while stack and array[stack[-1]] >= array[i]:
            stack.pop()
        right[i] = stack[-1] if stack else n
        stack.append(i)

    # 计算最大矩形面积
    for i in range(n):
        width = right[i] - left[i] - 1
        max_area = max(max_area, width * array[i])

    return max_area

知识总结

新知识点

  1. 单调栈

    • 用于快速求解数组中每个元素的左右边界。
    • 适用于「第一个小于某值」或「第一个大于某值」的问题。
  2. 滑动窗口优化

    • 简化暴力计算中的重复操作,减少时间复杂度。
  3. 最大矩形问题模型化

    • 将矩形问题转化为柱状图问题,利用分而治之思想。

理解与建议

  • 对于入门同学:

    • 从基础问题入手,理解单调栈的逻辑(如求解下一个更大元素)。
    • 逐步尝试应用到实际场景,如最大矩形面积或直方图问题。

学习计划

刷题计划

  1. 每天三题

    • 选择简单、中等、困难各一题。
    • 确保时间集中在 1-2 小时内完成。
  2. 错题本记录

    • 将错误的思路和正确解法进行对比。
    • 重点记录不熟悉的算法(如单调栈、动态规划等)。

利用错题进行针对性学习

  1. 归类错题:

    • 按题型(栈、队列、二分等)分类,明确薄弱环节。
  2. 针对性练习:

    • 通过 MarsCode AI 提供的类似题目进行强化训练。

工具运用

结合 MarsCode AI 的学习方法

  1. 实时代码评测

    • 利用 MarsCode AI 的代码评测功能,快速验证代码的正确性。
  2. 错题推荐

    • MarsCode AI 根据错题记录自动推荐相似题目,帮助巩固知识点。
  3. 题目解析和提示

    • 使用 MarsCode AI 的解析功能,了解复杂问题的拆解过程。

学习资源结合

  • 与经典算法书籍结合,如《算法导论》。
  • 结合可视化工具(如 Python Tutor)动态演示栈操作过程。

实用建议

  1. 多与 AI 互动,快速解决疑惑。
  2. 定期复盘,总结常见思路和模式。
  3. 参与算法竞赛或社区讨论,获取更多思维拓展的机会。