题目链接:最大矩形面积问题 - MarsCode
问题描述
小S最近在分析一个数组数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 个相邻元素时,如何计算它们所能形成的最大矩形面积。 对于 个相邻的元素,我们定义其矩形的最大面积为: 即, 的值为这 个相邻元素中的最小值乘以 。现在,小S希望你能帮他找出对于任意 , 的最大值。
解题思路
1.暴力解法
- 对于每个可能的
k(从 1 到n),遍历数组,计算每个k个相邻元素的矩形面积,并记录最大值。 - 时间复杂度为
O(n^2),对于较大的n可能不够高效。
2.优化思路
- 使用单调栈来优化查找最小值的过程。
- 单调栈可以帮助我们在
O(n)时间内找到每个元素作为最小值时,左右两边第一个比它小的元素的位置。
单调栈是什么?
单调栈(Monotonic Stack)是一种特殊类型的栈,栈中的元素保持单调递增或单调递减的顺序。单调栈通常用于解决需要查找某个元素左右两边第一个比它小(或大)的元素的问题。
单调栈的工作原理
单调递增栈:
- 栈中的元素保持单调递增的顺序,当遇到一个新元素时,如果它比栈顶元素小,则弹出栈顶元素,直到栈为空或者栈顶元素小于新元素。这样,栈顶元素就是当前元素左边第一个比它小的元素。
单调递减栈原理与以上类似。
算法步骤
-
初始化:
- 创建一个单调栈,用于存储数组元素的索引。
- 创建两个数组
left和right,分别用于存储每个元素左边和右边第一个比它小的元素的索引。
-
计算
left数组:- 遍历数组,对于每个元素,如果栈顶元素对应的值大于当前元素,则弹出栈顶元素,直到栈为空或者栈顶元素对应的值小于当前元素。
- 当前元素的
left值为栈顶元素的索引(如果栈为空则为 -1)。 - 将当前元素的索引入栈。
-
计算
right数组:- 从右往左遍历数组,类似地计算每个元素右边第一个比它小的元素的索引。
-
计算最大矩形面积:
- 对于每个元素,计算以它为最小值时的矩形面积,并更新最大面积。
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)