最大矩形面积问题
一、问题重现
问题描述
小S最近在分析一个数组 h1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 k 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 k 个相邻的元素,我们定义其矩形的最大面积为:
R(k)=k×min(h[i],h[i+1],...,h[i+k−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])
即,R(k)的值为这 kk 个相邻元素中的最小值乘以 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
二、解题思路
问题理解
我们需要在一个数组中找到任意 k 个相邻元素所能形成的最大矩形面积。这个矩形面积的计算方式是:k 个相邻元素中的最小值乘以 k。
数据结构选择
由于我们需要频繁地查找最小值,并且需要遍历所有可能的 k 值(从 1 到 n),我们可以考虑使用单调栈,用于理清元素大小关系,并快速找到最小值。
算法步骤
-
初始化:
- 使用一个单调栈来存储数组元素的索引。
- 使用一个变量
max_area来记录最大矩形面积。
-
遍历数组:
- 对于每个元素,将其索引压入单调栈中。
- 当栈顶元素大于当前元素时,弹出栈顶元素,并计算以栈顶元素为最小值的矩形面积。
-
计算面积:
- 对于每个弹出的栈顶元素,计算以该元素为最小值的矩形面积,并更新
max_area。
- 对于每个弹出的栈顶元素,计算以该元素为最小值的矩形面积,并更新
-
处理剩余元素:
- 遍历结束后,栈中可能还有元素,依次弹出并计算面积。
三、代码实现
def solution(n, array):
stack = [] # 单调栈,存储索引
max_area = 0
for i in range(n):
while stack and array[stack[-1]] > array[i]:
# 弹出栈顶元素并计算面积
height = array[stack.pop()]
width = i if not stack else i - stack[-1] - 1
max_area = max(max_area, height * width)
stack.append(i)
# 处理剩余元素
while stack:
height = array[stack.pop()]
width = n if not stack else n - stack[-1] - 1
max_area = max(max_area, height * width)
return max_area
四、算法复杂度分析
时间复杂度
-
遍历数组:代码中使用了一个
for循环来遍历数组中的每个元素,时间复杂度为O(n),其中n是数组的长度。 -
单调栈操作:在
for循环中,每个元素最多会被压入和弹出栈一次。因此,单调栈的操作总时间复杂度为O(n)。 -
处理剩余元素:在遍历结束后,栈中可能还剩下一些元素,需要依次弹出并计算面积。这部分操作的时间复杂度也是
O(n)。
整个算法的时间复杂度为 O(n)。
空间复杂度
-
单调栈:单调栈最多存储
n个元素的索引,空间复杂度为O(n)。 -
其他变量: 其他变量(如
max_area)的空间复杂度为O(1)。
整个算法的空间复杂度为 O(n)。