"最大矩形面积问题“题解 | 豆包MarsCode AI刷题

93 阅读4分钟

最大矩形面积问题 —— 从思路到实现

这道题目从一维数组出发,要求我们在任意长度 ( k ) 的连续子区间中,找到面积最大的矩形。本文将通过问题分析、解题思路到代码实现,逐步剖析问题的解决方案。


问题描述

小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. 子区间遍历:需要遍历所有可能的区间长度 ( k ),以及每个长度对应的起点 ( i )。
  2. 最小值计算:在区间 ([i, i+k-1]) 中找到最小值。这个步骤是计算效率的关键。
  3. 最大值更新:动态维护当前找到的最大矩形面积。

解题思路

针对问题特点,我们可以从最简单的暴力枚举法入手,再逐步优化:

  1. 暴力枚举法

    • 遍历所有可能的区间长度 ( k ) 和起点 ( i )。
    • 对于每个区间,使用 min() 函数计算其最小值,并计算面积。
    • 更新全局最大面积。
    • 缺点:复杂度较高,尤其是在区间最小值的计算上存在大量重复。
  2. 优化方向

    • 减少重复计算:通过动态规划或者单调栈的方法,可以避免重复计算最小值。
    • 降低时间复杂度:将复杂度从 ( O(n^3) ) 降低到 ( O(n^2) ) 或更低。

暴力枚举法实现

下面是基于暴力枚举的初始代码实现:

def solution(n, array):
    # 初始化最大面积
    max_area = 0

    # 遍历所有可能的区间长度 k
    for k in range(1, n + 1):  
        # 遍历所有可能的区间起点 i
        for i in range(n - k + 1):  
            # 找到当前区间的最小值
            min_height = min(array[i:i + k])
            # 计算当前区间的面积
            area = k * min_height
            # 更新最大面积
            max_area = max(max_area, area)
    
    return max_area

代码详解

  1. 初始化最大面积

    • max_area 初始值为 0,表示当前找到的最大矩形面积。
  2. 遍历所有区间长度 ( k )

    • 外层循环从 ( k = 1 ) 到 ( n ),表示当前考虑的区间长度。
  3. 遍历区间的起始位置 ( i )

    • 内层循环从 ( i = 0 ) 到 ( n-k ),表示当前区间的起始点。
  4. 计算区间的最小值

    • 使用 min(array[i:i+k]) 找到区间中的最小高度。
  5. 更新最大面积

    • 将当前区间的面积与 max_area 进行比较,保留较大的值。

算法复杂度分析

  • 时间复杂度:( O(n^3) )

    • 外层循环 ( k ) 遍历 ( n ) 次。
    • 内层循环 ( i ) 遍历 ( n-k ) 次,平均约为 ( n/2 )。
    • 每次计算最小值需要 ( O(k) ) 的复杂度。
    • 总体复杂度为 ( O(n^3) )。
  • 空间复杂度:( O(1) )

    • 只使用了常数空间存储最大面积。

优化思路

  1. 动态规划优化最小值计算

    • 构建一个辅助二维数组 min_table[i][k],存储从位置 ( i ) 开始,长度为 ( k ) 的区间最小值。
    • 状态转移方程: [ \text{min_table}[i][k] = \min(\text{min_table}[i][k-1], \text{array}[i+k-1]) ]
    • 预处理后,每次查询最小值的复杂度为 ( O(1) )。
  2. 单调队列优化

    • 使用单调队列维护当前区间的最小值,从而将最小值查询的复杂度降低到 ( O(1) )。

思考与总结

这道题的难点在于:

  1. 如何高效计算区间的最小值;
  2. 如何动态更新最大矩形面积。

暴力解法清晰直观,但在数据规模较大时性能会受到限制。通过动态规划或单调队列的优化,可以显著提高算法效率。