青训营X豆包MarsCode 最大矩形面积问题解析与总结 | 豆包MarsCode AI刷题

179 阅读4分钟

image.png

最大矩形面积问题的解析与总结

在学习算法的过程中,“最大矩形面积问题”是一道经典的题目,既考验对数组和区间的理解,也涉及栈的应用和优化技巧。本文将以这道题为例,从题目分析到代码实现,再到学习心得,为大家提供一份详尽的刷题解析和方法论。


一、题目解析

题目描述

我们有一个数组,每个元素代表一个高度,要求在其中找到相邻 kkk 个元素所能形成的最大矩形面积。矩形面积的计算公式是:

R(k)=k×min⁡(h[i],h[i+1],…,h[i+k−1])R(k) = k \times \min(h[i], h[i+1], \dots, h[i+k-1])R(k)=k×min(h[i],h[i+1],…,h[i+k−1])

其中,min⁡\minmin 表示取 kkk 个高度的最小值。

题目理解

这道题的核心是解决两个问题:

  1. 如何高效找到任意区间的最小值?

    • 暴力方法是直接遍历区间取最小值,时间复杂度 O(n2)O(n^2)O(n2)。
    • 优化方法是利用单调栈快速计算区间左右边界。
  2. 如何计算最大面积?

    • 面积计算的公式为 height×width\text{height} \times \text{width}height×width,需要准确找到矩形的高度(最小值)和宽度。
样例分析

输入

  • 样例1:数组为 [1, 2, 3, 4, 5],最大面积为 9。
  • 样例2:数组为 [5, 4, 3, 2, 1, 6],最大面积为 9。
  • 样例3:数组为 [4, 4, 4, 4],最大面积为 16。

可以观察到:

  • 最大面积的矩形通常出现在高度接近的区间中。
  • 高效解法需要找到每个高度的“作用范围”。

二、解题思路

1. 暴力方法

遍历数组中所有的区间,分别计算每个区间的最小值和面积,记录其中的最大值。
缺点:时间复杂度 O(n2)O(n^2)O(n2),无法通过较大规模的数据。

2. 优化方法:单调栈

核心思想

  • 单调栈是一种特殊的数据结构,用来高效找到每个柱形的左右边界。
  • 栈中的元素按高度递增存储,保证在遇到较低高度时可以快速弹出进行面积计算。

步骤

  1. 遍历数组,记录每个高度的索引。
  2. 如果当前高度小于栈顶高度,弹出栈顶元素,计算面积: 面积=高度×宽度\text{面积} = \text{高度} \times \text{宽度}面积=高度×宽度 宽度的计算通过栈中前一个元素的位置确定。
  3. 遍历结束后,将栈中剩余的元素依次弹出计算面积。

时间复杂度:O(n)O(n)O(n)。


三、代码实现

以下是基于单调栈的 Python 实现: def solution(n, array): # 初始化结果 max_area = 0

# 单调递增栈,存储下标
stack = []
left = [-1] * n  # 每个元素左侧第一个小于它的下标
right = [n] * n  # 每个元素右侧第一个小于它的下标

# 确定左边界
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

if name == "main": # Add your test cases here

print(solution(5, [1, 2, 3, 4, 5]) == 9)

四、知识点总结

1. 单调栈的应用

单调栈是一种高效解决“区间”类问题的数据结构,常用于:

  • 直方图最大矩形问题:本题的核心思想。
  • 接雨水问题:计算高度差形成的水量。
  • 滑动窗口最值:高效求解动态窗口的最大或最小值。
2. 边界条件的处理
  • 在原数组末尾添加高度为 0 的哨兵,确保最后能够清空栈并计算所有可能的矩形面积。
  • 栈为空时的特殊处理:宽度取当前索引值。
3. 时间复杂度分析
  • 每个元素最多被压入和弹出栈一次,整体复杂度 O(n)O(n)O(n)。
  • 空间复杂度 O(n)O(n)O(n),主要用于栈存储。

五、学习心得与建议

1. 如何高效刷题
  • 选择经典题目:如本题,涉及单调栈的使用和区间计算,能够帮助巩固数据结构和算法思维。
  • 从简单到复杂:先理解暴力解法,再优化为高效算法,逐步加深对问题的理解。
2. 错题的价值
  • 将错误归类为数据结构(如栈)或算法思想(如贪心、动态规划),反复练习直到完全掌握。
  • 在重新做错题时,尝试优化代码风格和复杂度。
3. 工具辅助
  • 使用豆包MarsCode AI等智能工具进行代码批改,可以快速定位错误并优化实现。
  • 借助视频讲解、竞赛题库等资源,提升刷题效率和广度。