题目解析:数组中相邻元素最大矩形面积
题目描述
本题要求计算一个高度数组中任意 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 值的矩形面积,最终返回其中的最大值。
测试样例分析
-
样例 1:
n = 5, array = [1, 2, 3, 4, 5]- 最大矩形面积出现在
k=3时,对应区域[3, 4, 5],最小高度为3,面积为3 × 3 = 9。
- 最大矩形面积出现在
-
样例 2:
n = 6, array = [5, 4, 3, 2, 1, 6]- 最大矩形面积出现在
k=3时,对应区域[3, 2, 1],最小高度为3,面积为3 × 3 = 9。
- 最大矩形面积出现在
-
样例 3:
n = 4, array = [4, 4, 4, 4]- 无论选择哪段区域,最小高度始终为
4,最大矩形面积为4 × 4 = 16。
- 无论选择哪段区域,最小高度始终为
解题思路
这道题可以通过暴力方法解决,但暴力方法的时间复杂度较高。为提高效率,我们可以采用优化思路,如单调栈来快速计算每个高度所能支撑的最大宽度。
方法一:暴力枚举
- 遍历所有可能的
k(相邻元素的数量)。 - 对于每个
k,计算所有可能的起始位置i,统计对应区间的最小高度。 - 计算面积并更新最大值。
- 时间复杂度:
外层k循环为 O(n)O(n),内层i循环为 O(n−k+1)O(n-k+1),且每次区间计算最小值需要 O(k)O(k)。
总体时间复杂度为 O(n3)O(n^3)。 - 适用场景:小规模数组。
方法二:单调栈优化
使用单调栈快速计算每个高度所能扩展的最大宽度,从而避免重复计算:
- 对于每个柱子高度,找到其左侧和右侧最近的比它低的柱子位置。
- 计算每个柱子作为最小高度时的最大矩形面积。
- 时间复杂度:
单调栈处理时间为 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. 区间最小值的高效处理
在暴力解法中,每次都需要重新计算区间的最小值,效率低下。而单调栈能够快速确定每个高度的扩展范围,从而避免重复计算。
学习建议与刷题计划
-
刷题计划
- 每周练习 2-3 道涉及区间问题的题目(如柱状图最大面积、滑动窗口最大值)。
- 重点掌握单调栈的使用,包括其思想和应用场景。
-
高效学习方法
- 分步骤学习:从暴力解法入手,逐步优化,理解每个优化步骤的意义。
- 总结模板:通过多次练习总结单调栈的通用模板,方便后续应用。
-
错题复盘
- 针对时间复杂度过高或思路不清晰的解法,复盘问题所在,并重新设计思路。
工具运用
-
借助豆包MarsCode AI
- 使用题库分类功能,集中练习“单调栈”相关题目。
- 借助解析功能,理解题目的核心思想与高效解法。
-
结合其他资源
- LeetCode、书籍《算法导论》等资源补充相关理论知识。
- 使用可视化工具(如在线栈模拟器)直观理解单调栈的运行过程。
总结
通过这道题目,我们掌握了:
- 单调栈在区间问题中的高效应用;
- 如何逐步优化暴力解法并降低时间复杂度;
- 结合工具与学习资源,形成高效的刷题方法。
未来可以继续在类似问题中巩固这些知识,并尝试将单调栈的思想迁移到更多复杂场景中,提升算法能力!