AI刷题丨最大矩形面积问题

71 阅读3分钟
### 问题描述

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

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

𝑅(𝑘)=𝑘×𝑚𝑖𝑛(ℎ[𝑖],ℎ[𝑖+1],...,ℎ[𝑖+𝑘−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

即,𝑅(𝑘)R(k) 的值为这 𝑘k 个相邻元素中的最小值乘以 𝑘k。现在,小S希望你能帮他找出对于任意 𝑘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

先让ai给个题解:
我们需要找到一个方法来计算对于任意 𝑘k,由 𝑘k 个相邻元素形成的矩形的最大面积 𝑅(𝑘)R(k) 的最大值。这个问题可以通过动态规划来解决。

首先,我们定义一个数组 𝑑𝑝[𝑖][𝑗]dp[i][j] 来表示以 ℎ[𝑖]h[i] 结尾的连续 𝑗j 个元素的最小高度乘以 𝑗j 的值。我们的目标是找到所有 𝑑𝑝[𝑖][𝑗]dp[i][j] 中的最大值。

我们可以通过以下步骤来填充 𝑑𝑝dp 数组:

  1. 初始化 𝑑𝑝[𝑖][1]=ℎ[𝑖]dp[i][1]=h[i],因为单个元素的矩形面积就是它本身的高度。
  2. 对于每个 𝑗j 从 2 到 𝑛n,更新 𝑑𝑝[𝑖][𝑗]dp[i][j] 为 min⁡(ℎ[𝑖],ℎ[𝑖−1],…,ℎ[𝑖−𝑗+1])×𝑗min(h[i],h[i−1],…,h[i−j+1])×j。
  3. 同时,我们需要更新 𝑑𝑝[𝑖][𝑗]dp[i][j] 为 max⁡(𝑑𝑝[𝑖][𝑗],𝑑𝑝[𝑖−1][𝑗],𝑑𝑝[𝑖−1][𝑗−1]+ℎ[𝑖]×(𝑗−1))max(dp[i][j],dp[i−1][j],dp[i−1][j−1]+h[i]×(j−1)),以确保我们考虑了所有可能的连续子数组。

最后,我们遍历整个 𝑑𝑝dp 数组,找到最大的值。
ai选择用动态规划解,但是我选择用单调栈求解:

def solution(n, array):
    max_area = 0
    stack = []
    array = [0] + array + [0]  # 添加虚拟的0以便处理边界情况

    for i, h in enumerate(array):
        while stack and array[stack[-1]] > h:
            height = array[stack.pop()]
            j = i - stack[-1] - 1 if stack else i
            max_area = max(max_area, height * j)
        stack.append(i)

    return max_area

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 3, 4, 5]) == 9)
    print(solution(6, [5, 4, 3, 2, 1, 6]) == 9)
    print(solution(4, [4, 4, 4, 4]) == 16)
  1. 初始化:创建一个空栈,用于存储索引,以及一个数组来存储每个元素左边第一个比它大的元素的索引,另一个数组来存储每个元素右边第一个比它小的元素的索引。
  2. 填充左边索引数组:从左到右遍历数组,对于每个元素,如果栈为空或者栈顶元素对应的高度大于当前元素的高度,将当前索引入栈。如果栈顶元素对应的高度小于或等于当前元素的高度,弹出栈顶元素,直到栈为空或者栈顶元素对应的高度大于当前元素的高度。当前元素的左边索引是栈顶元素的索引。
  3. 填充右边索引数组:从右到左遍历数组,对于每个元素,如果栈为空或者栈顶元素对应的高度小于当前元素的高度,将当前索引入栈。如果栈顶元素对应的高度大于或等于当前元素的高度,弹出栈顶元素,直到栈为空或者栈顶元素对应的高度小于当前元素的高度。当前元素的右边索引是栈顶元素的索引。
  4. 计算最大面积:对于每个元素 ℎ[𝑖]h[i],计算以 ℎ[𝑖]h[i] 为最小高度的 𝑘k 个相邻元素的最大面积。这可以通过检查 ℎ[𝑖]h[i] 左边和右边的索引来完成。对于每个可能的 𝑘k,计算 𝑅(𝑘)=𝑘×ℎ[𝑖]R(k)=k×h[i],并更新最大面积。
  5. 返回最大面积:在所有元素和所有可能的 𝑘k 中找到的最大面积就是答案。