当前位置: 首页 > news >正文

单调栈应用介绍

单调栈应用介绍

  • 定义
  • 应用场景
  • 实现模板
  • 具体示例
    • 下一个最大元素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虚拟机或服务器一台 若依前后端分离项目&#xff1a;可在下面拉取 RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供了 Vue3 的版本 二、环…...

PH47代码框架功能速查

1. PH47框架逻辑层全局引用对象 全局引用 功能简介 快速访问 bus 数据总线系统功能实现&#xff0c;如对总线数据项读写操作等 数据总线bus drv 驱动层功能实现&#xff0c;如飞控板相关的各种硬件传感器设备进行操作等 驱动层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&#xff0c;定义了用于在 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…...

温湿传感器(学习笔记下)

接着我们温湿传感器上半部分的学习&#xff0c;现在我们学习接下来的部分&#xff0c;编写GXHTC3驱动程序&#xff0c;也就是给gxhtc3.c文件添加代码&#xff0c;我们要判断gxhtc3芯片是否存在和正常&#xff0c;就要先读取gxhtc3的ID号,根据gxhtc3的数据手册&#xff0c;读取命…...

期刊论文写作之word模板

一、zotero参考文献使用 下载zotero软件&#xff0c;请搜索相关帖子或者小破站即可&#xff1b; 把pdf拖到zotero软件里面&#xff0c;直接拉进去&#xff1b; 下面建立一个word演示&#xff1a; 1.导入pdf点击红框部分&#xff0c;根据期刊要求选择参考文献样式&#xff0…...

雷池社区版OPEN API使用教程

OPEN API使用教程 新版本接口支持API Token鉴权 接口文档官方没有提供&#xff0c;有需要可以自行爬取&#xff0c;爬了几个&#xff0c;其实也很方便 使用条件 需要使用默认的 admin 用户登录才可见此功能版本需要 > 6.6.0 使用方法 1.在系统管理创建API TOKEN 2.发…...

LSTM(Long Short-Term Memory,长短期记忆网络)在高端局效果如何

lstm 杂乱数据分析 LSTM&#xff08;Long Short-Term Memory&#xff0c;长短期记忆网络&#xff09;在高端局&#xff0c;即复杂的机器学习和深度学习应用中&#xff0c;展现出了其独特的优势和广泛的应用价值。以下是对LSTM在高端局中的详细解析&#xff1a; 一、LSTM的优势…...

模组操作宝典:4种关机重启技巧,让你的设备运行无忧

今天我说的是关于关机重启技巧。 给4G模组VBAT断电关机&#xff0c;模组关机前未能及时退出当前基站&#xff0c;会有什么影响呢&#xff1f; 基站会误以为设备还在线&#xff0c;下次开机仍会拿着上次驻网信息去连基站。基站一看&#xff0c;上次链接还在——认为你是非法设…...

利用API接口实现旺店通和金蝶系统的无缝数据对接

旺店通销售出库对接金蝶销售订单(线下)的技术实现 在企业日常运营中&#xff0c;数据的高效流转和准确对接是确保业务顺畅运行的关键。本文将聚焦于一个具体案例&#xff1a;如何通过轻易云数据集成平台&#xff0c;实现旺店通企业奇门的数据无缝对接到金蝶云星空系统。我们将…...

热题100(hash)

热题100&#xff08;Hash&#xff09; 三道题目 1.两数之和&#xff08;√&#xff09; 49.字母异位词分组&#xff08;题解&#xff09; 128.最长连续序列(题解) 思路 第1题简单hash映射&#xff0c;O(n) 第49题,关键点在于Hashmap的形式&#xff0c;‘HashMap<Stri…...

Ubuntu下Mysql修改默认存储路径

首先声明&#xff0c;亲身经验&#xff0c;自己实践&#xff0c;网上百度了好几个帖子&#xff0c;全是坑&#xff0c;都TMD的不行&#xff0c;修改各种配置文件&#xff0c;就是服务起不来&#xff0c;有以下几种配置文件需要修改 第一个文件/etc/mysql/my.cnf 这个文件是存…...

LVGL移植教程(超详细)——基于GD32F303X系列MCU

版本&#xff1a;LVGL Kernel V8.3.0&#xff0c;运行压力测试Demo Stress首先放一张最终Stress Demo 运行图&#xff1a; 一、准备 1. GD32 Keil工程 准备任意一个屏幕可以正常显示的GD32工程&#xff1a; 2. LVGL源码 最新版现在已经是V9.2了&#xff0c;这里我选择了…...

《计算机原理与系统结构》学习系列——处理器(中)

系列文章目录 目录 流水线数据通路与控制概述5个流水级指令周期与流水级 流水线性能流水线时钟周期的长度T和数量cycles流水线性能 流水线数据通路流水线寄存器流水线分析图形化流水线流水线控制 流水线数据通路与控制 概述 5个流水级 指令周期与流水级 单周期实现中&#x…...

深入解析 OceanBase 数据库中的局部索引和全局索引

深入解析 OceanBase 数据库中的局部索引和全局索引 引言 在分布式数据库中&#xff0c;索引的设计对于优化查询性能至关重要。OceanBase 作为一款高性能的分布式关系数据库&#xff0c;支持局部索引和全局索引两种索引类型。理解这两种索引的特点和适用场景&#xff0c;对于数…...

2024防晒衣市场社媒营销洞察报告

2024年&#xff0c;硬防晒已经从单一的户外场景&#xff0c;扩展到通勤、外出游玩、穿搭等更多场景&#xff0c;多样化的需求导致的消费群体不断扩大&#xff0c;“防晒经济”迎来自己的主场时刻。 当前&#xff0c;防晒衣不仅需要满足不用场景的灵活切换&#xff0c;还要满足多…...

【Ubuntu20.04 Visual Studio Code安装】【VSCODE】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、打开VSCOE官网二、下载VSODE的Ubuntu版本三、安装VSCODE软件包四、导入工作空间(添加工作空间目录)五、安装插件&#xff1a;1.安装简体中文包2.安装ros插件…...

贪心算法day(1)

1.将数组和减半的最少操作次数 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;创建大跟堆将最大的数进行减半 注意点&#xff1a;double t queue.poll()会将queue队列数字减少一个后再除以2&#xff0c;queue.offer(queue.poll(&#xff09;/…...

窗口函数sql使用总结

一、开窗 基础知识&#xff1a;窗口分析函数 &#xff08;1&#xff09;LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值 第一个参数为列名&#xff0c;第二个参数为往上第n行&#xff08;可选&#xff0c;默认为1&#xff09;&#xff0c;第三个参数为默认值&#xff08;当往…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题&#xff0c; 因为搜索范围是有界的&#xff0c;上界最大木板长度补充的全部木料长度&#xff0c;下界最小木板长度&#xff1b; 即left0,right10^6; 我们可以设置一个候选值x(mid)&#xff0c;将木板的长度全部都补充到x&#xff0c;如果成功…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...