问题描述
小S最近在分析一个数组 h1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 k 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 k 个相邻的元素,我们定义其矩形的最大面积为:
R(k)=k×min(h[i],h[i+1],...,h[i+k−1])
即,R(k) 的值为这 k 个相邻元素中的最小值乘以 k。现在,小S希望你能帮他找出对于任意 k,R(k) 的最大值。
核心难点
- 多长度区间的最小值计算: 对于长度为 k 的所有区间,我们需要找到区间内的最小值。这在暴力法中需要 O(k×N) 的时间复杂度,显然不够高效。
- 面积的优化计算: 最大矩形面积的计算需要综合考虑不同柱子的高度以及它们覆盖的区间长度。这需要从全局的角度,快速找到每个柱子的最大可扩展范围。
解题思路
-
单调栈优化:
- 通过单调栈,可以快速找到每个柱子的左边界和右边界,即该柱子作为最小高度时,能够覆盖的最大区间。
- 利用单调栈直接求得每个柱子的最大矩形面积,从而解决整个问题。
详细步骤
构建单调栈:
使用单调栈,可以高效求解每个柱子作为最小高度时的最大扩展区间,从而直接得到最大矩形面积。
-
定义左右边界:
- 左边界 left[i]:柱子 h[i] 左边第一个比它低的位置。
- 右边界 right[i]:柱子 h[i] 右边第一个比它低的位置。
-
构建单调栈:
- 使用一个单调递增栈来遍历高度数组h。
- 当发现当前高度小于栈顶对应的高度时,弹出栈顶,更新其左右边界。
- 遍历完成后,栈中剩余元素的边界由数组边界决定。
-
计算最大矩形面积:
- 对于每个柱子 h[i],计算其作为最小高度时形成的矩形面积: Area=h[i]×(right[i]−left[i]−1)
- 遍历所有柱子,记录最大面积。
代码实现
以下是 Python 的代码实现:
def solution(n, array):
# Edit your code here
left = [-1] * n # 存储每个柱子的左边界
right = [n] * n # 存储每个柱子的右边界
stack = []
# 计算左边界
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 = []
# 计算右边界
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):
max_area = max(max_area, array[i] * (right[i] - left[i] - 1))
return max_area
时间复杂度
- 单调栈操作:每个柱子入栈、出栈一次,时间复杂度为 O(N)。
- 遍历计算面积:时间复杂度为 O(N)。
- 总时间复杂度为 O(N)。
空间复杂度
- 主要用于存储栈和边界数组,空间复杂度为 O(N)。