题目解析:数组中相邻元素最大矩形面积| 豆包MarsCode AI刷题

45 阅读5分钟

题目解析:数组中相邻元素最大矩形面积

题目描述
本题要求计算一个高度数组中任意 k 个相邻元素形成的矩形的最大面积。矩形的高度取决于这 k 个相邻元素中的最小值,面积计算公式为:

R(k)=k×min⁡(h[i],h[i+1],...,h[i+k−1])R(k) = k \times \min(h[i], h[i+1], ..., h[i+k-1])

我们需要找到所有可能的 k 值的矩形面积,最终返回其中的最大值。

测试样例分析

  • 样例 1n = 5, array = [1, 2, 3, 4, 5]

    • 最大矩形面积出现在 k=3 时,对应区域 [3, 4, 5],最小高度为 3,面积为 3 × 3 = 9
  • 样例 2n = 6, array = [5, 4, 3, 2, 1, 6]

    • 最大矩形面积出现在 k=3 时,对应区域 [3, 2, 1],最小高度为 3,面积为 3 × 3 = 9
  • 样例 3n = 4, array = [4, 4, 4, 4]

    • 无论选择哪段区域,最小高度始终为 4,最大矩形面积为 4 × 4 = 16

解题思路

这道题可以通过暴力方法解决,但暴力方法的时间复杂度较高。为提高效率,我们可以采用优化思路,如单调栈来快速计算每个高度所能支撑的最大宽度。

方法一:暴力枚举

  1. 遍历所有可能的 k(相邻元素的数量)。
  2. 对于每个 k,计算所有可能的起始位置 i,统计对应区间的最小高度。
  3. 计算面积并更新最大值。
  • 时间复杂度
    外层 k 循环为 O(n)O(n),内层 i 循环为 O(n−k+1)O(n-k+1),且每次区间计算最小值需要 O(k)O(k)。
    总体时间复杂度为 O(n3)O(n^3)。
  • 适用场景:小规模数组。

方法二:单调栈优化

使用单调栈快速计算每个高度所能扩展的最大宽度,从而避免重复计算:

  1. 对于每个柱子高度,找到其左侧和右侧最近的比它低的柱子位置。
  2. 计算每个柱子作为最小高度时的最大矩形面积。
  • 时间复杂度
    单调栈处理时间为 O(n)O(n)。
    总体时间复杂度为 O(n)O(n)。
  • 适用场景:大规模数组。

代码详解

方法一:暴力枚举

def solution(n, array):
    max_area = 0
    # 遍历所有可能的 k
    for k in range(1, n + 1):
        # 遍历所有可能的起始位置 i
        for i in range(n - k + 1):
            # 计算 k 个相邻元素的最小高度
            min_height = min(array[i:i + k])
            # 计算当前面积
            current_area = k * min_height
            # 更新最大面积
            max_area = max(max_area, current_area)
    return max_area

# 测试用例
print(solution(5, [1, 2, 3, 4, 5]))  # 输出 9
print(solution(6, [5, 4, 3, 2, 1, 6]))  # 输出 9
print(solution(4, [4, 4, 4, 4]))  # 输出 16

方法二:单调栈

def solution_optimized(n, array):
    # 在数组左右添加两个哨兵,用于简化边界计算
    array = [0] + array + [0]
    stack = []
    max_area = 0

    for i in range(len(array)):
        # 当当前柱子高度小于栈顶高度时,计算栈顶的最大面积
        while stack and array[i] < array[stack[-1]]:
            height = array[stack.pop()]
            width = i - stack[-1] - 1
            max_area = max(max_area, height * width)
        stack.append(i)

    return max_area

# 测试用例
print(solution_optimized(5, [1, 2, 3, 4, 5]))  # 输出 9
print(solution_optimized(6, [5, 4, 3, 2, 1, 6]))  # 输出 9
print(solution_optimized(4, [4, 4, 4, 4]))  # 输出 16

知识总结

1. 单调栈的基本概念

单调栈是一种用于解决区间范围问题的高效数据结构。它的核心思想是通过维护一个单调递增或递减的栈,快速找到左侧和右侧的限制条件。

  • 典型应用

    • 柱状图中的最大矩形面积问题;
    • 求滑动窗口的最大值。

2. 区间最小值的高效处理

在暴力解法中,每次都需要重新计算区间的最小值,效率低下。而单调栈能够快速确定每个高度的扩展范围,从而避免重复计算。


学习建议与刷题计划

  1. 刷题计划

    • 每周练习 2-3 道涉及区间问题的题目(如柱状图最大面积、滑动窗口最大值)。
    • 重点掌握单调栈的使用,包括其思想和应用场景。
  2. 高效学习方法

    • 分步骤学习:从暴力解法入手,逐步优化,理解每个优化步骤的意义。
    • 总结模板:通过多次练习总结单调栈的通用模板,方便后续应用。
  3. 错题复盘

    • 针对时间复杂度过高或思路不清晰的解法,复盘问题所在,并重新设计思路。

工具运用

  1. 借助豆包MarsCode AI

    • 使用题库分类功能,集中练习“单调栈”相关题目。
    • 借助解析功能,理解题目的核心思想与高效解法。
  2. 结合其他资源

    • LeetCode、书籍《算法导论》等资源补充相关理论知识。
    • 使用可视化工具(如在线栈模拟器)直观理解单调栈的运行过程。

总结

通过这道题目,我们掌握了:

  1. 单调栈在区间问题中的高效应用;
  2. 如何逐步优化暴力解法并降低时间复杂度;
  3. 结合工具与学习资源,形成高效的刷题方法。

未来可以继续在类似问题中巩固这些知识,并尝试将单调栈的思想迁移到更多复杂场景中,提升算法能力!