最大矩形面积问题 | 豆包MarsCode AI 刷题

35 阅读4分钟

问题分析

问题背景

小S有一个数组 ℎ=[ℎ1,ℎ2,…,ℎ𝑁],每个元素 ℎ𝑖 代表某种高度。小S对这些高度感兴趣的是,当我们在数组中选取任意 𝑘 个相邻元素时,如何计算它们所能形成的最大矩形面积。

问题定义

对于任意 𝑘 个相邻的元素,我们定义其矩形的最大面积为: 𝑅(𝑘)=𝑘×min⁡(ℎ[𝑖],ℎ[𝑖+1],…,ℎ[𝑖+𝑘−1])

即,𝑅(𝑘) 的值为这 𝑘 个相邻元素中的最小值乘以 𝑘。现在,小S希望你能帮他找出对于任意 k,𝑅(𝑘) 的最大值。

输入

  • 一个整数 𝑁,表示数组的长度。
  • 一个整数数组 ℎ,长度为 𝑁。

输出

  • 一个整数,表示对于任意 𝑘,𝑅(𝑘) 的最大值。

解决思路

  1. 初始化变量

    • 初始化一个变量 max_area 为 0,用于存储最终的最大面积。
    • 初始化一个单调栈 stack 用于计算每个元素左边和右边第一个小于它的元素的位置。
    • 初始化两个数组 left 和 right,分别存储每个元素左边和右边第一个小于它的元素的位置。
  2. 计算左边界

    • 使用单调栈从左到右遍历数组,计算每个元素左边第一个小于它的元素的位置,并存储在 left 数组中。
  3. 计算右边界

    • 使用单调栈从右到左遍历数组,计算每个元素右边第一个小于它的元素的位置,并存储在 right 数组中。
  4. 计算最大面积

    • 遍历数组,对于每个元素,计算以其为最小值的矩形的宽度 width,并计算面积 area
    • 更新 max_area,记录当前的最大面积。

具体步骤

  1. 初始化变量

    • max_area = 0
    • stack = []
    • left = [0] * n
    • right = [0] * n
  2. 计算左边界

    • 遍历数组,对于每个元素 i

      • 使用单调栈找到左边第一个小于 array[i] 的元素的位置。
      • 将位置存储在 left[i] 中。
      • 将当前索引 i 压入栈中。
  3. 计算右边界

    • 清空栈。

    • 从右到左遍历数组,对于每个元素 i

      • 使用单调栈找到右边第一个小于 array[i] 的元素的位置。
      • 将位置存储在 right[i] 中。
      • 将当前索引 i 压入栈中。
  4. 计算最大面积

    • 遍历数组,对于每个元素 i

      • 计算宽度 width = right[i] - left[i] - 1
      • 计算面积 area = array[i] * width
      • 更新 max_area,记录当前的最大面积。
  5. 返回结果

    • 返回 max_area

代码实现

def solution(n, array):
# Edit your code here
# 初始化单调栈和左右边界数组
stack = []
left = [0] * n
right = [0] * n
# 计算左边界
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):
    width = right[i] - left[i] - 1
    max_area = max(max_area, array[i] * width)

return max_area
if __name__ == "__main__":
# Add your test cases here

print(solution(5, [1, 2, 3, 4, 5]) == 9)

总结

通过解决这道关于计算最大矩形面积的问题,我深刻体会到了算法优化的重要性。最初,我尝试使用暴力解法,即枚举所有可能的 𝑘 值并计算每个子数组的最小值,但这种方法的时间复杂度高达 𝑂(𝑁2),在大数据量下显然不可行。因此,我转向了更高效的解决方案。使用单调栈来预处理每个元素的左右边界,这一技巧极大地提高了算法的效率。通过两次遍历数组,分别计算每个元素左边和右边第一个小于它的元素的位置,可以在 𝑂(𝑁) 的时间复杂度内完成预处理。这一过程不仅简化了后续的计算,还使得整体算法更加清晰和高效。在实际编码过程中,我也遇到了一些细节问题,比如边界条件的处理和栈的清空操作。通过调试和测试,我逐渐完善了代码,最终得到了正确的结果。这让我意识到,编写高效的算法不仅仅是理论上的设计,还需要在实践中不断调试和优化。