单调栈:高效解决算法问题的数据结构

发布时间:2026/11/3 17:41:51

单调栈:高效解决算法问题的数据结构 1. 单调栈算法竞赛与面试中的高效解题利器在算法竞赛和编程面试中单调栈是一种极其高效且实用的数据结构。它通过维护栈内元素的单调性能够在O(n)时间复杂度内解决一系列看似复杂的问题。我第一次接触单调栈是在解决LeetCode第84题柱状图中最大的矩形时当时暴力解法超时让我意识到必须寻找更优解而单调栈正是那把钥匙。单调栈的核心思想很简单在遍历数组时维护一个栈结构保证栈内元素始终保持单调递增或单调递减的顺序。这种结构特别适合解决寻找下一个更大/更小元素这类问题。在实际应用中单调栈可以高效解决四大类问题寻找下一个更大/更小元素计算柱状图最大矩形面积处理滑动窗口极值问题解决某些特殊的动态规划问题2. 单调栈的核心原理与实现步骤2.1 单调栈的基本性质单调栈有两种基本形式单调递增栈栈底到栈顶元素值递增单调递减栈栈底到栈顶元素值递减选择哪种单调性取决于具体问题当需要找下一个更大元素时使用单调递增栈当需要找下一个更小元素时使用单调递减栈关键提示单调栈中通常存储数组索引而非元素值因为索引可以同时提供位置和值信息这在计算距离、面积等问题时非常有用。2.2 单调栈的通用实现模板以下是单调栈的Python通用实现模板def monotonic_stack(nums): stack [] # 存储索引 result [0] * len(nums) # 存储结果 for i in range(len(nums)): # 维护栈的单调性 while stack and nums[i] nums[stack[-1]]: # 这里决定递增/递减 top_idx stack.pop() # 处理弹出的元素 result[top_idx] i - top_idx # 根据问题调整 stack.append(i) # 处理栈中剩余元素 while stack: top_idx stack.pop() result[top_idx] -1 # 或根据问题需求赋值 return result2.3 单调栈的四步解题法根据多年刷题经验我总结出使用单调栈的四步解题法确定栈的单调性明确问题要找的是更大还是更小元素找更大元素→单调递增栈找更小元素→单调递减栈确定栈中存储内容90%情况下存储索引更优特殊情况下可能需要存储值或复合数据设计弹栈处理逻辑这是解题的核心不同问题处理方式不同可能需要计算距离、面积、或更新结果数组处理剩余元素遍历结束后栈中可能还有未处理元素根据问题要求给这些元素赋默认值3. 经典问题实战解析3.1 下一个更大元素问题LeetCode #496问题重述给定两个数组nums1和nums2其中nums1是nums2的子集。对于nums1中的每个元素找到它在nums2中对应位置右侧的第一个更大元素。解法分析这道题有两种解法暴力法时间复杂度O(m*n)单调栈法时间复杂度O(mn)单调栈解法思路预处理nums2使用单调栈找到每个元素的下一个更大元素将结果存入哈希表便于快速查询遍历nums1直接从哈希表获取结果优化后的代码实现class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) - List[int]: stack [] next_greater {} # 逆序遍历更容易理解 for num in reversed(nums2): while stack and num stack[-1]: stack.pop() next_greater[num] stack[-1] if stack else -1 stack.append(num) return [next_greater[num] for num in nums1]复杂度分析时间复杂度O(mn)其中m是nums1长度n是nums2长度空间复杂度O(n)用于存储哈希表和栈3.2 每日温度问题LeetCode #739问题重述给定每日温度数组返回一个数组表示需要等待多少天才能遇到更高温度。解法分析这是典型的下一个更大元素变种需要计算的是天数差而非元素值。关键点使用单调递减栈栈中存储索引以便计算天数差遇到更高温度时更新结果数组代码实现与注释class Solution: def dailyTemperatures(self, T: List[int]) - List[int]: n len(T) res [0] * n stack [] # 存储索引 for i in range(n): # 当前温度比栈顶温度高时 while stack and T[i] T[stack[-1]]: prev_idx stack.pop() res[prev_idx] i - prev_idx # 计算天数差 stack.append(i) return res实战技巧逆序遍历也可以解决这个问题但正序更直观初始化结果数组为0这样未处理的元素自动为0存储索引而非温度值便于计算天数差3.3 柱状图中最大矩形LeetCode #84问题重述给定柱状图的高度数组求能勾勒出的最大矩形面积。解法分析这是单调栈的经典应用关键在于找到每根柱子左右第一个比它矮的柱子。解题思路使用单调递增栈遍历时维护栈的递增性当遇到较矮柱子时计算弹出柱子的最大面积面积计算公式高度×宽度(右边界-左边界-1)优化后的代码实现class Solution: def largestRectangleArea(self, heights: List[int]) - int: heights [0] heights [0] # 添加哨兵 stack [] 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²)降到O(n)性能提升显著。这也是单调栈强大之处的典型例证。4. 单调栈的高级应用与技巧4.1 处理环形数组问题有些问题如LeetCode #503下一个更大元素II涉及环形数组。解决方法是将数组翻倍然后用单调栈处理。class Solution: def nextGreaterElements(self, nums: List[int]) - List[int]: n len(nums) res [-1] * n stack [] for i in range(2 * n): while stack and nums[i % n] nums[stack[-1]]: res[stack.pop()] nums[i % n] if i n: stack.append(i) return res4.2 二维矩阵中的单调栈应用单调栈也可以扩展到二维问题如LeetCode #85最大矩形。解法是将二维问题转化为一系列柱状图问题然后使用单调栈求解。4.3 常见错误与调试技巧在实现单调栈时容易犯以下错误混淆单调递增和单调递减栈忘记处理栈中剩余元素边界条件处理不当如空栈访问调试建议打印栈状态和中间结果用小例子手动模拟算法过程特别注意索引越界问题5. 单调栈的复杂度分析与适用场景5.1 时间复杂度分析单调栈的典型时间复杂度为O(n)因为每个元素最多入栈一次、出栈一次即使有嵌套循环总操作次数也是2n次5.2 空间复杂度分析空间复杂度一般为O(n)主要用于存储栈结构存储结果数组5.3 适用问题特征适合用单调栈解决的问题通常具有以下特征需要寻找下一个更大/更小元素需要计算基于元素位置的面积或距离问题可以转化为寻找边界的问题5.4 不适用场景以下情况可能不适合使用单调栈需要随机访问历史数据问题与元素顺序无关数据量非常小暴力法足够6. 单调栈的变种与扩展6.1 单调队列单调队列是单调栈的扩展可以在两端操作适用于滑动窗口问题。6.2 带权值的单调栈某些问题需要在栈中存储额外信息如累积和或其他统计量。6.3 多维度单调栈处理更复杂的问题时可能需要同时维护多个单调栈。在实际刷题过程中我发现单调栈的掌握需要大量练习。建议从简单题开始逐步过渡到难题同时注意总结各类问题的共性和特性。我个人的练习路线是#496 → #739 → #503 → #84 → #85由浅入深循序渐进。
延伸阅读

更多相关文章

2026/11/3 17:41:51

PHP数组取值全攻略:从基础下标到安全路径提取与批量筛选

数组取值这件事,说它是PHP里最基础的操作也不为过,但我见过太多写了几年业务代码的人,面对一个嵌套三四层的数组时,依然会下意识地写一串foreach加if,最后还漏掉了键名不存在的情况。标题里问的是“怎么取出数组中的值…

2026/11/3 17:41:51

生日悖论:从直觉误区到代码验证的完整拆解

生日悖论这个问题,我在面试新人的时候特别喜欢拿来当开胃题。不是因为它难,恰恰是因为它太反直觉了——很多人第一反应是“50个人里有两个同一天生日?概率应该很小吧”,然后一算发现接近97%,当场愣住。这道题表面上是概…

2026/11/3 17:36:50

OpenVLA-oft模型在RoboTwin2.0中的实战应用

1. 项目背景与核心价值 在智能机器人开发领域,视觉语言动作模型(VLA)正成为实现复杂任务自主执行的关键技术。RoboTwin2.0作为机器人数字孪生仿真平台,为VLA模型的训练提供了理想的测试环境。最近开源的OpenVLA-oft模型因其轻量化和高效性备受关注&#…

2026/11/3 18:47:09

ByteFF2:AI力场如何实现量子级液体预测突破?

ByteFF2:AI力场如何实现量子级液体预测突破? 【免费下载链接】byteff2 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/byteff2 导语:字节跳动最新发布的ByteFF2力场模型,通过融合图神经网络与量子力学数据…

2026/11/3 18:47:09

RLPR-Qwen2.5:无验证器也能实现推理飞跃?

RLPR-Qwen2.5:无验证器也能实现推理飞跃? 【免费下载链接】RLPR-Qwen2.5-7B-Base 项目地址: https://ai.gitcode.com/OpenBMB/RLPR-Qwen2.5-7B-Base 导语:OpenBMB团队推出的RLPR-Qwen2.5-7B-Base模型,通过创新的RLPR框架实…

2026/11/3 18:47:09

阿里通义Wan2.1图生视频模型轻量化部署与效率优化指南

阿里通义Wan2.1图生视频模型轻量化部署与效率优化指南 阿里通义Wan2.1图生视频模型是一款高性能的AI视频生成工具,能够将文本描述或图像转化为高质量视频内容。本文将从技术原理、环境搭建、参数调优到行业应用四个维度,全面解析该模型的轻量化部署方案与…

2026/11/3 18:47:09

Moonlight-16B震撼登场:Muon优化效率提升2倍

Moonlight-16B震撼登场:Muon优化效率提升2倍 导语:MoonshotAI推出的Moonlight-16B-A3B大语言模型,通过Muon优化器实现训练效率翻倍,以5.7T tokens训练量超越同类模型性能,重新定义大模型训练效率新标准。 行业现状&a…

2026/11/3 18:47:09

3步颠覆视频创作:阿里通义Wan2.1量化模型实战指南

3步颠覆视频创作:阿里通义Wan2.1量化模型实战指南 让设计师/教育者/创作者0代码实现专业级动态视频生成 🔍 痛点诊断:视频创作的三大困境 你是否曾遇到:明明创意十足,却被困在Premiere的时间轴里整整三天?为…

2026/11/3 7:47:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/3 1:04:48

STM32实战:基于MAX14431数字隔离器的SPI隔离通信方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/3 1:04:48

工业SPI隔离通信设计:MAX14431BAEE+与STM32L4A6RG实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/3 1:04:48

STM32+NRF24L01无线抢答器:硬件设计、通信协议与低功耗实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/3 7:47:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑