最大矩形面积问题
问题描述
小S最近在分析一个数组 h1,h2,...,hN 数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。
对于 kk 个相邻的元素,我们定义其矩形的最大面积为:
R(k)=k × min(h[i],h[i+1],...,h[i+k−1])
即,R(k)的值为这 k 个相邻元素中的最小值乘以 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 ) 来得到。可以使用单调栈来高效地解决这个问题。
解题思路
- 单调栈法:
- 为了快速找到每一个柱子(元素)为高度的最大矩形面积,我们可以利用单调栈来计算“每个柱子的左右边界”。
- 我们在遍历数组时,使用单调递增栈来找到每个柱子左边第一个小于它的柱子的位置和右边第一个小于它的柱子的位置。
- 这样,对于每一个高度 ( h[i] ),我们可以计算以 ( h[i] ) 为最小高度时的最大矩形宽度,从而得到最大矩形面积。
- 算法步骤:
- 遍历数组,使用单调栈记录每个元素的左边和右边第一个比它小的位置。
- 根据这些边界来计算以当前元素高度为最小高度的矩形面积。
- 遍历所有可能的矩形面积,得到最大值。
- 复杂度分析:
- 时间复杂度:( O(n) ),因为每个元素最多被栈操作两次(一次进栈,一次出栈)。
- 空间复杂度:( O(n) ),用于存储栈和边界信息。
代码实现
def solution(n,array):
if n == 0:
return 0
# 存储每个柱子的左右边界
left = [0] * n
right = [n] * n
# 计算每个柱子的左边第一个小于它的元素索引
stack = []
for i in range(n):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
left[i] = stack[-1] + 1 if stack else 0
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]))
return max_area
# 测试样例
print(solution([1, 2, 3, 4, 5])) # 输出: 9
print(solution([5, 4, 3, 2, 1, 6])) # 输出: 9
print(solution([4, 4, 4, 4])) # 输出: 16
解释
- 通过计算每个元素为最小高度的矩形宽度,可以确保我们找到所有可能的连续子数组形成的矩形面积。
- 代码中的
left和right数组分别存储了每个位置的左边界和右边界,从而我们可以通过计算矩形的宽度,乘以高度得到面积。
- 最终我们输出最大面积即为答案。
经验总结
1. 合理理解题目需求,建立解题思路
- 这个问题是经典的“最大矩形面积”问题的变体,实际上是要找到数组中任意 kkk 个连续元素组成的矩形的最大面积。豆包 Marscode AI 插件通常会先分析需求,帮助找到问题的实质,并可能自动生成适合的解题思路(如单调栈法)。
2. 利用插件的算法模板功能
- Marscode AI 插件通常内置多种算法模板(如单调栈、动态规划等),可以快速生成适用于此类矩形面积问题的模板代码。
- 在此题中,Marscode AI 会识别到单调栈是高效解法,可以借助其模板减少开发时间。
3. 自动注释功能帮助理解复杂逻辑
- 单调栈方法本身不容易理解,尤其是如何找到左右边界等细节。Marscode AI 的自动注释功能会在代码中添加解释性注释,让逻辑清晰化。
- 比如,对于每一步出栈和入栈操作,Marscode 会在注释中说明具体含义,这对于复杂的算法实现尤为有用。