问题描述
小S最近在分析一个数组 ,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 个相邻元素时,如何计算它们所能形成的最大矩形面积。 对于 个相邻的元素,我们定义其矩形的最大面积为: 即, 的值为这 个相邻元素中的最小值乘以 。现在,小S希望你能帮他找出对于任意 , 的最大值。
测试样例
样例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
思路:
- 单调栈:我们维护一个栈,栈中的元素是数组的索引,栈中的高度元素从栈底到栈顶是递增的。
- 遍历:遍历数组,对于每个元素,判断当前元素是否小于栈顶元素。如果小于,则弹出栈顶元素,计算以该元素为高度的矩形面积。如果大于或等于栈顶元素,则将当前元素的索引压入栈中。
- 结束处理:当遍历完成后,栈中可能还剩下一些元素,需要处理这些元素,计算出它们所能构成的最大矩形面积
。
代码如下:
def solution(n, array):
stack = []
max_area = 0
for i in range(n):
# 处理当前元素,保证栈中的元素是递增的
while stack and array[stack[-1]] > array[i]:
h = array[stack.pop()] # 弹出栈顶元素,得到矩形的高度
w = i if not stack else i - stack[-1] - 1 # 计算宽度
max_area = max(max_area, h * w) # 更新最大面积
stack.append(i) # 将当前元素的索引压入栈
# 处理栈中剩余的元素
while stack:
h = array[stack.pop()]
w = n if not stack else n - stack[-1] - 1
max_area = max(max_area, h * w)
return max_area
if __name__ == "__main__":
# Add your test cases here
print(solution(5, [1, 2, 3, 4, 5]) == 9)
时间复杂度:
- 由于每个元素最多被压入栈一次,并且最多被弹出一次,时间复杂度是 (O(n)),相较于暴力法的 (O(n^2)),效率大大提高
。
举例:
假设 array = [2, 1, 5, 6, 2, 3],运行该算法的过程如下:
- 遇到 2,压栈;
- 遇到 1,弹出 2 计算面积,更新最大面积,压 1;
- 遇到 5,压栈;
- 遇到 6,压栈;
- 遇到 2,弹出 6、5 计算面积,更新最大面积,压 2;
- 遇到 3,压栈,最终处理栈中剩余元素,得到最大矩形面积。
这个优化方案是解决此问题的经典方法,非常高效。