最大矩形面积问题
这道题是经典的最大矩形面积问题的变形。问题给定一个数组,每个元素表示高度。我们需要找出任意相邻的 ( k ) 个高度所能形成的最大矩形面积。
问题描述
小S最近在分析一个数组 h1,h2,...,hNh1,h2,...,hN,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 kk 个相邻的元素,我们定义其矩形的最大面积为:
即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kk,R(k)R(k) 的最大值。
问题分析
在这个问题中,我们定义矩形面积的计算方法如下: 对于 ( k ) 个相邻的高度,我们可以形成的最大矩形面积为:
其中 ( h[i] ) 表示数组中第 ( i ) 个高度。
核心问题就是:如何找到所有相邻子数组的最小高度,并计算出面积。
难点
一开始,这个问题看上去可能需要枚举所有可能的 ( k ) 值,然后计算每个子数组的最小高度并求出面积。这种直接的暴力方法在小规模数据下可行,但在规模增大后,时间复杂度会迅速上升。因此,需要找到一种高效的解法。
在解决过程中,我学到了单调栈这种数据结构,可以用来有效地解决类似的最大矩形问题。通过单调栈,可以快速地找到每个高度作为最小高度时,能够扩展的最大宽度,从而快速计算出最大矩形面积。
题目等级
难度:中等偏上。虽然思路不难,但是我觉得需要实现细节较多。
解题思路
- 左右边界的确定:对于每个柱子,我们要确定它能延伸到的最远边界,即找到左边第一个小于它的高度和右边第一个小于它的高度的位置。这可以用单调栈来实现。
- 计算面积:对于每个柱子,利用它作为最低高度的矩形宽度为左右边界的差值,计算出面积。
- 返回最大值:在所有矩形面积中找出最大的值。
代码实现
代码实现如下:
def solution(n, array):
# 左边界数组,left[i]表示左边第一个小于array[i]的下标
left = [-1] * n
# 右边界数组,right[i]表示右边第一个小于array[i]的下标
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):
# 宽度为右边界 - 左边界 - 1
width = right[i] - left[i] - 1
area = array[i] * width
max_area = max(max_area, area)
return max_area
代码讲解
-
左边界和右边界:
- 利用单调栈确定每个柱子左边和右边第一个小于它的柱子位置。
- 这样可以快速确定每个柱子作为矩形最小高度的最大扩展宽度。
-
最大面积计算:
- 对于每个柱子,计算其可能的矩形面积并更新最大值。
测试样例分析
- 样例1:输入
[1, 2, 3, 4, 5],最大矩形面积是9。 - 样例2:输入
[5, 4, 3, 2, 1, 6],最大矩形面积也是9。 - 样例3:输入
[4, 4, 4, 4],最大矩形面积为16。
# 测试用例
if __name__ == "__main__":
print(solution(5, [1, 2, 3, 4, 5]) == 9) # 应输出 9
print(solution(6, [5, 4, 3, 2, 1, 6]) == 9) # 应输出 9
print(solution(4, [4, 4, 4, 4]) == 16) # 应输出 16
总结
这个题目的关键在于利用单调栈找到每个柱子的左右边界,进而计算最大矩形面积。通过这道题,我加深了对单调栈的理解,特别是如何应用在寻找区间内最小值问题上。在实际应用中,单调栈是一种很高效的数据结构,特别适合处理类似矩形面积的最大值问题。