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

37 阅读3分钟

问题描述

小S最近在分析一个数组 h1,h2,...,hNh_1, h_2, ..., h_N,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。对于 kk 个相邻的元素,我们定义其矩形的最大面积为:R(k)=k×min(h[i],h[i+1],...,h[i+k1])R(k) = k \times min(h[i], h[i + 1], ..., h[i + k - 1])即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kkR(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 ,a = [4, 4, 4, 4] 输出:16

思路分析:

我们有一个数组 array,数组中的每个元素表示一个直方图的柱子的高度。我们要找出所有可能的连续柱子组合(至少一个柱子)中,能够覆盖的最大矩形面积。 关键点在于理解并确定每个柱子作为矩形的“高度”时,可以向左右两边分别延伸多少距离,使得以这个柱子为高所构成的矩形面积最大。

计算左右边界:

  1. 左侧边界:对于每个柱子 i,我们需要找到左边第一个比它低的柱子 left[i]。如果不存在,则默认为 -1。这样,以 i 为中心向左扩展的宽度就是 i - left[i]
  2. 右侧边界:同样,我们需要找到右边第一个比它低的柱子 right[i]。如果不存在,则默认为数组末尾 N。这样,以 i 为中心向右扩展的宽度是 right[i] - i

矩阵面积计算:

对于每个柱子 i

  • 它向左的最大扩展宽度为 i - left[i]
  • 向右的最大扩展宽度为 right[i] - i
  • 所以以这个柱子为高的矩形面积为:height[i] * (right[i] - left[i] - 1)

最终答案是所有柱子可能的矩形面积中的最大值。

代码实现:

from typing import List
def find_boundaries(heights: List[int]) -> tuple:
    stack = []
    n = len(heights)

    left = [-1] * n
    right = [n] * n

    for i in range(n):
        while stack and heights[stack[-1]] >= heights[i]:
            right[stack.pop()] = i
        if stack:
            left[i] = stack[-1]
        stack.append(i)

    return left, right

def solution(n: int, array: List[int]) -> int:
    left, right = find_boundaries(array)

    max_area = 0
    for i in range(n):
        width = right[i] - left[i] - 1
        area = array[i] * width
        max_area = max(max_area, area)

    return max_area

if __name__ == "__main__":
    assert solution(5, [1, 2, 3, 4, 5]) == 9
    print("测试通过!")

代码中的 find_boundaries 函数解析

这个函数用于计算每个柱子的左右边界。

  1. 初始化两个数组 left 和 right,分别记录每个柱子的左边界和右边界,默认情况下,左边界为 -1,右边界为数组的最后一个下标加一。

  2. 利用两个单调递增的栈来分别计算 left 和 right

    • 当前柱子 i 要入栈时,需要弹出所有高于等于它的柱子,直到遇到第一个小于它的柱子或栈空;
    • 栈顶元素就是当前柱子左边第一个比它低的柱子(若存在),或栈空则无;
    • 右边相同的道理,只不过方向相反。

总结

  1. 使用两个辅助栈来快速找到每个柱子的左右边界,减少了不必要的比较次数。
  2. 通过动态规划的方式,每次更新最大面积,直至找到全局最优解。
  3. 最后返回所有可能的矩形面积中的最大值作为解。