news 2026/11/3 6:36:56

柱形图最大矩形问题:单调栈解法与应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
柱形图最大矩形问题:单调栈解法与应用

1. 问题背景与核心挑战

柱形图最大矩形问题(LeetCode 84题,原输入有误)是算法面试中的经典难题,要求在一系列相邻且宽度为1的柱形中,找出能勾勒出的最大矩形面积。这个问题看似简单,但O(n²)的暴力解法在面试中毫无竞争力,而最优解的单调栈思路又需要巧妙的思维转换。

我第一次遇到这个问题时,尝试用双指针法折腾了两小时无果,直到理解栈如何维护"最近较小值"的特性才豁然开朗。这个算法在现实中有广泛应用场景,比如计算卫星地图中的最大建筑占地面积、股票分析中的支撑阻力位识别等。

2. 暴力解法与性能瓶颈

2.1 双重循环实现

最直观的方法是对于每个柱子,向左右两侧扩展直到遇到更矮的柱子:

def largestRectangleArea(heights): max_area = 0 n = len(heights) for i in range(n): left = i while left >= 0 and heights[left] >= heights[i]: left -= 1 right = i while right < n and heights[right] >= heights[i]: right += 1 max_area = max(max_area, (right - left - 1) * heights[i]) return max_area

时间复杂度O(n²),在LeetCode上会超时。主要浪费在于重复计算——当柱子高度呈递增序列时,内层while循环每次都要从头扫描。

2.2 暴力法的优化空间

可以通过预处理来存储每个位置左右边界:

  • 从左向右扫描记录lastLessFromLeft数组
  • 从右向左扫描记录lastLessFromRight数组 这样虽然仍为O(n²),但实际运行时间会缩短。不过面试官期待的是更优解。

3. 单调栈最优解法

3.1 算法核心思想

维护一个栈,存储的是可能作为矩形左边界的柱子索引。当遇到新柱子时:

  1. 比栈顶高:直接入栈(当前柱子可能作为右边界的左边界)
  2. 比栈顶低:弹出栈顶并计算面积,直到栈顶柱子比当前矮

关键点:栈内柱子高度始终保持单调递增,这样栈内每个柱子的"下一个更小"就是当前柱子

3.2 完整实现代码

def largestRectangleArea(heights): stack = [] heights = [0] + heights + [0] # 边界处理技巧 max_area = 0 for i in range(len(heights)): while stack and heights[i] < heights[stack[-1]]: h = heights[stack.pop()] w = i - stack[-1] - 1 max_area = max(max_area, h * w) stack.append(i) return max_area

这个O(n)解法有几个精妙之处:

  1. 首尾补0避免空栈判断
  2. 宽度计算利用栈的单调性
  3. 每个柱子只入栈出栈一次

4. 算法正确性证明

4.1 单调栈的数学性质

设栈内元素为s[0...k],满足: heights[s[0]] < heights[s[1]] < ... < heights[s[k]]

当遇到heights[i] < heights[s[k]]时:

  • 对于弹出的s[k],其右边界显然是i
  • 左边界是s[k-1](因为s[k]是s[k-1]之后第一个>=它的柱子)

4.2 边界条件处理

首尾补0的两个作用:

  1. 开头的0保证第一个真实柱子能顺利入栈
  2. 结尾的0保证所有柱子都能被弹出计算

如果不补0,代码中需要增加大量判空逻辑,比如:

while stack and heights[i] < heights[stack[-1]]: h = heights[stack.pop()] w = i - stack[-1] - 1 if stack else i # 处理栈空情况 max_area = max(max_area, h * w)

5. 实际应用与变种问题

5.1 真实场景应用案例

  • 地图分析:找出卫星图像中最大的连续建筑区域
  • 股票分析:识别K线图中的关键支撑/阻力位
  • 广告投放:计算网页中最大可投放广告区域

5.2 常见变种题目

  1. 二维矩阵中的最大矩形(LeetCode 85题)
    • 解法:将矩阵逐行转化为柱形图高度
  2. 带障碍物的最大矩形
    • 需要修改高度计算规则
  3. 最大正方形(LeetCode 221题)
    • 类似思路但需要额外维护宽度

6. 调试技巧与常见错误

6.1 典型错误案例

错误实现1:漏处理相等情况

while stack and heights[i] <= heights[stack[-1]]: # 应该用<

会导致重复计算相同高度的柱子

错误实现2:宽度计算错误

w = i - stack[-1] # 应该-1

少减1会导致宽度多算一个单位

6.2 调试建议

  1. 先用小测试用例验证:
    • [2,1,2] → 最大面积3
    • [3,1,3,2,2] → 最大面积6
  2. 打印栈状态和中间结果:
print(f"i={i}, stack={stack}, max_area={max_area}")
  1. 可视化柱形图辅助理解

7. 性能优化进阶

7.1 空间优化方案

原始算法需要O(n)空间存储栈,可以进一步优化:

  1. 分治法:O(nlogn)时间复杂度
  2. 线段树:O(nlogn)但实现复杂

不过在实际面试中,单调栈解法已经足够优秀。

7.2 并行计算可能性

对于超大规模数据(如地图分析),可以将柱形图分段:

  1. 切分数据块并计算局部最大值
  2. 合并时处理边界区域的矩形 但要注意负载均衡和通信开销。

8. 面试实战要点

8.1 白板编码技巧

  1. 先说明暴力解法及其缺陷
  2. 引出单调栈思路时画图演示:
    • 画出柱形图和栈的变化过程
    • 标注关键步骤的面积计算
  3. 主动讨论边界条件(空输入、全等高等)

8.2 常见follow-up问题

  • 如何修改算法求最大正方形?
  • 如果柱子宽度不固定怎么处理?
  • 如何扩展到二维情况?

我在多次面试中总结的经验是:解释清楚"为什么栈要单调递增"这个核心点,就能让面试官认可你的理解深度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/3 6:36:24

BQ25895 5A开关充电设计:外围选型、寄存器配置与PCB布局排障

先说一个我在调试现场反复遇到的场景&#xff1a;一块手持设备的板子焊回来&#xff0c;插上适配器&#xff0c;电池指示灯亮了&#xff0c;但充电电流卡在 800mA 上不去&#xff0c;用手背碰一下 BQ25895 背面的板子&#xff0c;烫得缩手。把示波器探头搭到 SW 引脚上&#xf…

作者头像 李华
网站建设 2026/11/3 6:36:24

PLM系统升级与APQP数字化在汽车制造业的应用

1. PLM系统升级与制造业数字化转型背景在制造业向智能化转型的浪潮中&#xff0c;产品生命周期管理&#xff08;PLM&#xff09;系统正从传统的文档管理工具演变为企业研发创新的核心平台。我们团队最近实施的"全星研发项目管理APQP软件系统"项目&#xff0c;正是针对…

作者头像 李华
网站建设 2026/11/3 6:32:54

智能手机实现VLN数据采集:低成本高精度方案解析

1. 项目概述&#xff1a;手机端VLN数据采集的革命性突破视觉与语言导航&#xff08;VLN&#xff09;领域长期面临真实场景数据采集的高门槛问题。传统方案需要昂贵的激光雷达、深度相机或多传感器融合设备&#xff0c;而我们在实际项目中验证了一套仅用智能手机就能完成专业级V…

作者头像 李华
网站建设 2026/11/3 6:32:29

MySQL数据插入操作全解析与性能优化

1. MySQL数据插入基础与实战解析作为关系型数据库的核心操作之一&#xff0c;数据插入是每个开发者必须掌握的技能。今天我将结合多年数据库开发经验&#xff0c;详细拆解MySQL中INSERT语句的各种使用场景和实战技巧。无论你是刚接触MySQL的新手&#xff0c;还是需要优化批量插…

作者头像 李华
网站建设 2026/11/3 6:31:53

CMake工程实践:场景化配置与模块化设计指南

1. CMake工程场景解析&#xff1a;为什么需要关注特定场景&#xff1f;在CMake的实际工程应用中&#xff0c;我发现很多开发者容易陷入一个误区——过度关注通用配置而忽略了场景化适配。就像装修房子时只考虑水电基础&#xff0c;却没想好各个房间的具体用途。经过多个工业级项…

作者头像 李华
网站建设 2026/11/3 6:31:31

技术解构与重构:从医学解剖到AI认知的三重浪潮

1. 技术解构与重构的三重浪潮人类文明发展史本质上是一部不断解构与重构自我的历史。最近在调试一个多模态感知系统时&#xff0c;我注意到传感器数据融合的过程与人类认知世界的机制惊人地相似——都需要先分解再整合。这让我开始思考技术发展对人类自我认知的深层影响。医学时…

作者头像 李华