单调栈应用介绍
单调栈应用介绍
- 定义
- 应用场景
- 实现模板
- 具体示例
- 下一个最大元素I
- 问题描述
- 问题分析
- 代码实现
- 柱状图中最大的矩形
- 问题描述
- 问题分析
- 代码实现
- 接雨水
- 问题描述
- 问题分析
- 代码实现
- 最大宽度坡
- 问题描述
- 问题分析
- 代码实现
- 132模式
- 问题描述
- 问题分析
- 代码实现
定义
栈(Stack)是另一种操作受限的线性表,只允许元素从栈的顶端进顶端出,具有后进先出(LIFO)的特性。但单调栈(Monotonic Stack)是一种特殊的栈,在满足栈特性的基础上,栈内元素从栈底到栈顶具有单调性。如果栈底到栈顶元素是单调递减,则称为单调递减栈;如果栈底到栈顶元素是单调递增,则称为单调递增栈。
单调栈具有以下特性:
- 新元素加入栈顶时,需要进行单调性维护,弹出不满足单调性的栈顶元素
- 当前解计算是在出栈的时候进行的
应用场景
- 下一个最大元素,对应单调递减栈
- 下一个最小元素,对应单调递增栈
- 上一个最大元素,反向入栈,即从数据尾部往前遍历,对应单调递减栈
- 上一个最小元素,反向入栈,即从数据尾部往前遍历,对应单调递增栈
以上是单调栈最基础的应用场景,很多问题也是对这些场景的变种,我们需要一针见血的直指问题核心。
实现模板
在代码实现上,主要涉及两个动作(动作之间的顺序需要根据具体问题场景灵活调整):
- 维护栈顶: 保证整个栈的单调性,新元素入栈时,及时弹出栈顶不满足单调性的元素
- 问题解计算逻辑:在弹出栈顶时,计算问题解
伪代码如下:
ans = 问题初始解
//tips:由于下面流程必须判断栈非空,某些场景下,可以构造一个不影响结果又能保证栈永远非空的初始化栈,这样就避免判断栈非空逻辑 ---
stack<栈内元素类型> stk = 初始化栈;
//正常处理流程
for(const auto& item: dataSource){while (!stk.empty() && checkMonotonic(stk.top(), item)) {//计算问题解ans = 问题解计算逻辑stk.pop();}stk.push(x);
}//在某些场景下,需要保证所有元素出栈 --- 可以通过一些辅助数据来 保证所有数据在上面流程中全部出栈,这样可以省略以下逻辑,保证代码简洁性
while (!stk.empty()) {//计算问题解ans = 问题解计算逻辑stk.pop();
}
单调栈的结构简单,应用形式灵活,需要结合具体问题灵活处理。
具体示例
下一个最大元素I
496. 下一个更大元素 I
问题描述
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
示例 1:
输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
示例 2:
输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。
问题分析
本题的问题描述看着挺复杂的,但由于nums1是nums2的子集,即nums1中的数值都在nums2中,且无重复数字,所以,这里的问题可以简化先为求nums2中每个元素的下一个最大元素,然后再取nums1中特定元素对应的下一个最大元素。
代码实现
class Solution {
public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {//适用hash map存储每个元素对应的下一个最大元素值unordered_map<int,int> preData;stack<int> stk;//使用单调递减栈求取每个元素的下一个最大元素for(int idx = nums2.size() - 1; idx >= 0; --idx){while(!stk.empty() && nums2[idx] >= stk.top()){stk.pop();}preData[nums2[idx]] = stk.empty() ? -1 : stk.top();stk.push(nums2[idx]);}vector<int> ans;//遍历每个元素取值for(int num: nums1){ans.push_back(preData[num]);}return ans;}
};
柱状图中最大的矩形
84. 柱状图中最大的矩形
问题描述
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:

输入: heights = [2,4]
输出: 4
问题分析
矩形面积的计算公式为 矩形面积 = 宽 ∗ 高 矩形面积= 宽 * 高 矩形面积=宽∗高,求最大面积需要遍历所有柱子,以该柱子为高的所有矩形面积中的最大面积。当计算某根柱子为高的矩形面积时,只需要确定宽度,即确定矩形的左右边界:
- 左边界:该柱子往左找到第一个比他矮的柱子
- 右边界:该柱子往右找到第一个比他矮的柱子

对应的代码实现如下:
class Solution {
public:int largestRectangleArea(vector<int>& heights) {int ans = 0;int size = heights.size();for(int idx = 0; idx < size; ++idx){//查找左边界:往左找第一个比他矮的柱子int left = idx;while(left > 0 && heights[left - 1] >= heights[idx]) left--;//查找右边界:往右找第一个比他矮的柱子int right = idx;while(right < size - 1 && heights[right + 1] >= heights[idx]) right++;ans = max(ans, heights[idx] * (right - left + 1));}return ans;}
};
这道题作为难度级别为Hard的题目,该实现提交后肯定会超时,超时的原因就是在确定左右边界时会做大量的来回比较,如果我们能够快速找到左右边界,那就ok了。在确定左右边界时,需要找到第一个比他矮的柱子,这不这是单调队列的经典应用场景吗?
对于该问题,需要往左和往右两个方向利用单调递增栈求其第一个比他矮的柱子。
代码实现
先利用单调递增栈分别求出当前柱子的左右边界,然后再计算所有柱子对应的矩形面积,最后取其中最大的矩形面积。
class Solution {
public:int largestRectangleArea(vector<int>& heights) {int size = heights.size();stack<int> stk;//左边界vector<int> left(size,0);for(int idx = 0; idx < size; ++idx){while(!stk.empty() && heights[stk.top()] >= heights[idx]) stk.pop();left[idx] = stk.empty() ? -1 : stk.top();stk.push(idx);}stk = stack<int>();//右边界vector<int> right(size,0);for相关文章:
单调栈应用介绍
单调栈应用介绍 定义应用场景实现模板具体示例下一个最大元素I问题描述问题分析代码实现柱状图中最大的矩形问题描述问题分析代码实现接雨水问题描述问题分析代码实现最大宽度坡问题描述问题分析代码实现132模式问题描述问题分析代码实现定义 栈(Stack)是另一种操作受限的线性…...
部署前后端分离若依项目--CentOS7Docker版
一、准备 centos7虚拟机或服务器一台 若依前后端分离项目:可在下面拉取 RuoYi-Vue: 🎉 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本 二、环…...
PH47代码框架功能速查
1. PH47框架逻辑层全局引用对象 全局引用 功能简介 快速访问 bus 数据总线系统功能实现,如对总线数据项读写操作等 数据总线bus drv 驱动层功能实现,如飞控板相关的各种硬件传感器设备进行操作等 驱动层drv mcu 对mcu的片内接口及设备进行操作…...
UVM寄存器模型:uvm_reg_adapter
文章目录 一、什么是uvm_reg_adapter1、what2、Example2.1、代码详解 二、如何使用uvm_reg_adapter三、为什么要引入uvm_reg_adapter 一、什么是uvm_reg_adapter 1、what uvm_reg_adapter继承于uvm_object,定义了用于在 uvm_reg_bus_op 和特定总线事务之间进行转换…...
总结OpenGL和pyrender安装和使用过程中的坑
目录 报错一:AttributeError: NoneType object has no attribute glGetError 报错二:ImportError: (Unable to load OpenGL library, OSMesa: cannot open shared object file: No such file or directory, OSMesa, None) 报错三:raise ImportError("Unable to load…...
温湿传感器(学习笔记下)
接着我们温湿传感器上半部分的学习,现在我们学习接下来的部分,编写GXHTC3驱动程序,也就是给gxhtc3.c文件添加代码,我们要判断gxhtc3芯片是否存在和正常,就要先读取gxhtc3的ID号,根据gxhtc3的数据手册,读取命…...
期刊论文写作之word模板
一、zotero参考文献使用 下载zotero软件,请搜索相关帖子或者小破站即可; 把pdf拖到zotero软件里面,直接拉进去; 下面建立一个word演示: 1.导入pdf点击红框部分,根据期刊要求选择参考文献样式࿰…...
雷池社区版OPEN API使用教程
OPEN API使用教程 新版本接口支持API Token鉴权 接口文档官方没有提供,有需要可以自行爬取,爬了几个,其实也很方便 使用条件 需要使用默认的 admin 用户登录才可见此功能版本需要 > 6.6.0 使用方法 1.在系统管理创建API TOKEN 2.发…...
LSTM(Long Short-Term Memory,长短期记忆网络)在高端局效果如何
lstm 杂乱数据分析 LSTM(Long Short-Term Memory,长短期记忆网络)在高端局,即复杂的机器学习和深度学习应用中,展现出了其独特的优势和广泛的应用价值。以下是对LSTM在高端局中的详细解析: 一、LSTM的优势…...
模组操作宝典:4种关机重启技巧,让你的设备运行无忧
今天我说的是关于关机重启技巧。 给4G模组VBAT断电关机,模组关机前未能及时退出当前基站,会有什么影响呢? 基站会误以为设备还在线,下次开机仍会拿着上次驻网信息去连基站。基站一看,上次链接还在——认为你是非法设…...
利用API接口实现旺店通和金蝶系统的无缝数据对接
旺店通销售出库对接金蝶销售订单(线下)的技术实现 在企业日常运营中,数据的高效流转和准确对接是确保业务顺畅运行的关键。本文将聚焦于一个具体案例:如何通过轻易云数据集成平台,实现旺店通企业奇门的数据无缝对接到金蝶云星空系统。我们将…...
热题100(hash)
热题100(Hash) 三道题目 1.两数之和(√) 49.字母异位词分组(题解) 128.最长连续序列(题解) 思路 第1题简单hash映射,O(n) 第49题,关键点在于Hashmap的形式,‘HashMap<Stri…...
Ubuntu下Mysql修改默认存储路径
首先声明,亲身经验,自己实践,网上百度了好几个帖子,全是坑,都TMD的不行,修改各种配置文件,就是服务起不来,有以下几种配置文件需要修改 第一个文件/etc/mysql/my.cnf 这个文件是存…...
LVGL移植教程(超详细)——基于GD32F303X系列MCU
版本:LVGL Kernel V8.3.0,运行压力测试Demo Stress首先放一张最终Stress Demo 运行图: 一、准备 1. GD32 Keil工程 准备任意一个屏幕可以正常显示的GD32工程: 2. LVGL源码 最新版现在已经是V9.2了,这里我选择了…...
《计算机原理与系统结构》学习系列——处理器(中)
系列文章目录 目录 流水线数据通路与控制概述5个流水级指令周期与流水级 流水线性能流水线时钟周期的长度T和数量cycles流水线性能 流水线数据通路流水线寄存器流水线分析图形化流水线流水线控制 流水线数据通路与控制 概述 5个流水级 指令周期与流水级 单周期实现中&#x…...
深入解析 OceanBase 数据库中的局部索引和全局索引
深入解析 OceanBase 数据库中的局部索引和全局索引 引言 在分布式数据库中,索引的设计对于优化查询性能至关重要。OceanBase 作为一款高性能的分布式关系数据库,支持局部索引和全局索引两种索引类型。理解这两种索引的特点和适用场景,对于数…...
2024防晒衣市场社媒营销洞察报告
2024年,硬防晒已经从单一的户外场景,扩展到通勤、外出游玩、穿搭等更多场景,多样化的需求导致的消费群体不断扩大,“防晒经济”迎来自己的主场时刻。 当前,防晒衣不仅需要满足不用场景的灵活切换,还要满足多…...
【Ubuntu20.04 Visual Studio Code安装】【VSCODE】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、打开VSCOE官网二、下载VSODE的Ubuntu版本三、安装VSCODE软件包四、导入工作空间(添加工作空间目录)五、安装插件:1.安装简体中文包2.安装ros插件…...
贪心算法day(1)
1.将数组和减半的最少操作次数 链接:. - 力扣(LeetCode) 思路:创建大跟堆将最大的数进行减半 注意点:double t queue.poll()会将queue队列数字减少一个后再除以2,queue.offer(queue.poll()/…...
窗口函数sql使用总结
一、开窗 基础知识:窗口分析函数 (1)LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值 第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
