📜  门| GATE-CS-2009 |第 53 题(1)

📅  最后修改于: 2023-12-03 15:28:43.389000             🧑  作者: Mango

题目描述

给定一个数组 arr[],其中每个元素表示该位置上的建筑物的高度。 它被表示为一个直方图中。 找到这个直方图中可以容纳的最大矩形的面积。

例如,在下面的图中,最大矩形的面积是 6*4=24

        _ _
       |   |   _ _ 
 _ _   |   |  |   |
|   |  |   |  |   |
|   |  |   |  |   |
|   |  |   |  |   |
-----------------

函数签名

def getMaxArea(arr: List[int]) -> int:
    pass
输入格式
  • arr: 长度为 $n$ 的整数列表,$0 \leq n \leq 10^6$,$0 \leq arr_i \leq 10^9$
输出格式
  • 返回一个整数,表示该直方图中可以容纳的最大矩形的面积

示例

assert getMaxArea([6, 2, 5, 4, 5, 1, 6]) == 12

解题思路

这是一个非常经典的问题,称为直方图中的最大矩形。一个简单的思路是穷举矩形,计算每个矩形的面积,取面积最大的一个。时间复杂度为 $O(n^3)$,无法通过本题。

更好的做法是,维护一个单调递增的栈。栈中维护的是直方图中的下标,而非直方图高度。依次遍历直方图中的每个高度,对于每个高度,它可以组成的最大面积的矩阵只可能在两种情况下出现:

  1. 当前高度比栈顶下标 top 所在的高度更高时,将其入栈。
  2. 当前高度比栈顶下标 top 所在的高度更低时,栈顶元素 top 的最大面积的矩阵已经找到。弹出栈顶元素 top,则其对应的矩阵的宽为 $i - stack[-1] - 1$,其中 i 为当前高度在直方图中的下标,stack[-1] 表示栈中下一个下标的前一个下标。

因此,只需将每个高度分别入栈和弹栈,时间复杂度为 $O(n)$,可以通过本题。

具体细节可以见代码实现。

代码实现

from typing import List


def getMaxArea(arr: List[int]) -> int:
    stack = [-1]
    max_area = 0
    n = len(arr)
    for i in range(n):
        while stack[-1] != -1 and arr[stack[-1]] > arr[i]:
            top = stack.pop()
            max_area = max(max_area, arr[top] * (i - stack[-1] - 1))
        stack.append(i)
    while stack[-1] != -1:
        top = stack.pop()
        max_area = max(max_area, arr[top] * (n - stack[-1] - 1))

    return max_area