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

69 阅读3分钟

题目链接:最大矩形面积问题 - MarsCode

问题描述

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

解题思路

1.暴力解法

  • 对于每个可能的 k(从 1 到 n),遍历数组,计算每个 k 个相邻元素的矩形面积,并记录最大值。
  • 时间复杂度为 O(n^2),对于较大的 n 可能不够高效。

2.优化思路

  • 使用单调栈来优化查找最小值的过程。
  • 单调栈可以帮助我们在 O(n) 时间内找到每个元素作为最小值时,左右两边第一个比它小的元素的位置。

单调栈是什么?

单调栈(Monotonic Stack)是一种特殊类型的栈,栈中的元素保持单调递增或单调递减的顺序。单调栈通常用于解决需要查找某个元素左右两边第一个比它小(或大)的元素的问题。

单调栈的工作原理

单调递增栈:

  • 栈中的元素保持单调递增的顺序,当遇到一个新元素时,如果它比栈顶元素小,则弹出栈顶元素,直到栈为空或者栈顶元素小于新元素。这样,栈顶元素就是当前元素左边第一个比它小的元素。

单调递减栈原理与以上类似。

算法步骤

  1. 初始化

    • 创建一个单调栈,用于存储数组元素的索引。
    • 创建两个数组 left 和 right,分别用于存储每个元素左边和右边第一个比它小的元素的索引。
  2. 计算 left 数组

    • 遍历数组,对于每个元素,如果栈顶元素对应的值大于当前元素,则弹出栈顶元素,直到栈为空或者栈顶元素对应的值小于当前元素。
    • 当前元素的 left 值为栈顶元素的索引(如果栈为空则为 -1)。
    • 将当前元素的索引入栈。
  3. 计算 right 数组

    • 从右往左遍历数组,类似地计算每个元素右边第一个比它小的元素的索引。
  4. 计算最大矩形面积

    • 对于每个元素,计算以它为最小值时的矩形面积,并更新最大面积。
def solution(n, array):
    # 初始化单调栈和左右边界数组
    stack = []
    left = [-1] * n
    right = [n] * n
    
    # 计算 left 数组
    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 = []
    
    # 计算 right 数组
    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)
    
    # 计算最大矩形面积
    max_area = 0
    for i in range(n):
        width = right[i] - left[i] - 1
        max_area = max(max_area, array[i] * width)
    
    return max_area

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 3, 4, 5]) == 9)