单调队列与单调栈<2>——单调栈

news2024/10/1 19:00:08

单调栈的定义

单调递增栈

  • 栈中元素从栈底到栈顶是递增的。

单调递减栈

  • 栈中元素从栈底到栈顶是递减的。

单调栈的核心内容

我们从左到右遍历元素,构造单调栈(从栈顶到栈底递增或减):在 i 从左往右遍历的过程中,我们可以用一个单调栈来保存 i 左边的所有元素(不包括 i 指向的元素),i 遍历一个元素单调栈就放入一个元素,每一个元素都必须入栈一次下标越大的元素越接近栈顶,下标越小的元素越接近栈底。

在每个新的元素入栈前从栈顶依次去除所有不合法的元素,因为这些元素会破坏单调性,直到栈顶小于或大于该入栈元素,此时元素可以入栈。

简单来说,就是在入栈时删掉不合法元素,保证栈的单调性。

单调栈的应用

寻找左边第一个比它小的数

例题

给定一个长度为 N 的数列,输出每个数左边第一个比它小的数,如果不存在则输出 −1。

Sol

朴素算法的时间复杂度为\Theta(N^2),所以考虑优化。

在元素入栈前从栈顶依次去除所有不合法元素,因为这些元素会破坏单调性,直到栈顶小于该入栈元素,此时元素可以入栈,栈的单调性没被破坏,并且此时的栈顶就是要寻找的答案——左边第一个比它小的数。

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=1;i<=n;i++){
		while(!stk.empty() && stk.top()>=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		else
			ans[i]=-1;
		stk.push(arr[i]);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找左边第一个比它大的数

和上面的思路相同。改变符号即可。

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=1;i<=n;i++){
		while(!stk.empty() && stk.top()<=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		else
			ans[i]=-1;
		stk.push(arr[i]);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找左边第一个比它小的数的下标

Sol

很简单,我们让栈维护的是下标即可。

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=1;i<=n;i++){
		while(!stk.empty() && arr[stk.top()]>=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		stk.push(i);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找左边第一个比它大的数的下标

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=1;i<=n;i++){
		while(!stk.empty() && arr[stk.top()]<=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		stk.push(i);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找右边第一个小于它的数

Sol

将数组倒序遍历即可。

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=n;i>0;i--){
		while(!stk.empty() && stk.top()>=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		else
			ans[i]=-1;
		stk.push(arr[i]);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找右边第一个大于它的数

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=n;i>0;i--){
		while(!stk.empty() && stk.top()<=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		else
			ans[i]=-1;
		stk.push(arr[i]);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找右边第一个小于它的数的下标

例题:P5788

Sol

和之前的思路相同。

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=n;i>0;i--){
		while(!stk.empty() && arr[stk.top()]>=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		stk.push(i);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

寻找右边第一个大于它的数的下标

Code

#include <bits/stdc++.h>
using namespace std;
int arr[maxn],ans[maxn];
stack<int> stk;
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>arr[i];
	for(int i=n;i>0;i--){
		while(!stk.empty() && arr[stk.top()]<=arr[i])
			stk.pop();//把栈内不合法的元素出栈
		if(!stk.empty())
			ans[i]=stk.top();//栈顶就是答案
		stk.push(i);
	}
	for(int i=1;i<=n;i++)
		cout<<ans[i]<<' ';
	return 0;
}

以上就是本期博客的全部内容了,我这就去更新 ABC372 的题解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2182955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【高频SQL基础50题】16-20

day by day. 目录 1.进店却未进行过交易的顾客 2.项目员工 I 3.销售分析III 4. 判断三角形 5. 电影评分 1.进店却未进行过交易的顾客 连接题。 思路&#xff1a;根据trans表中的visit_id号在 visits表中排除&#xff0c;再将剩下的合并相同客户&#xff08;累加visit…

300Kg载重履带式无人车底盘定制开发技术详解

关于300Kg载重履带式无人车底盘的定制开发技术&#xff0c;可以从以下几个方面进行详细解析&#xff1a; 一、总体设计思路 300Kg载重履带式无人车底盘的定制开发&#xff0c;旨在打造一款承载能力强、行驶稳定、适应复杂地形的无人运输平台。设计过程中需充分考虑动力系统的…

【C++ 前缀和 数论】1590. 使数组和能被 P 整除|2038

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 质数、最大公约数、菲蜀定理 LeetCode 1590. 使数组和能被 P 整除 给你一个正整数数组 nums&#xff0c;请你移除 最短 子数组&#xff08;可以为 空&#xff09;&am…

麒麟系统文件扩展名所表示的文件种类

图 1 .conf 配置文件&#xff0c;如图2&#xff1b; 图 2 .Deb 安装包&#xff0c;如图3&#xff1b; 图 3 .sh 可执行程序&#xff0c;如图4&#xff1b; 图 4 .tar或者.gz 压缩包&#xff0c;如图5&#xff1b; 图 5 .bin 二进制文件&#xff0c;如图6&#xff1b; 图 6…

android compose ScrollableTabRow indicator 指示器设置宽度

.requiredWidth(30.dp) Box(modifier Modifier.background(Color.LightGray).fillMaxWidth()) {ScrollableTabRow(selectedTabIndex selectedTabIndex, // 默认选中第一个标签containerColor ColorPageBg,edgePadding 1.dp, // 内容与边缘的距离indicator { tabPositions…

房地产政策持续利好,龙湖“好房子”新品观萃入市受市场认可

《港湾商业观察》王璐 经过疫情以来持续调整的房地产市场&#xff0c;外界预期&#xff0c;在政策利好效应带动下&#xff0c;行业将稳健向前。 9月26日&#xff0c;中央政治局会议对房地产的表述内容释放出极强的政策宽松信号。会议首次明确提出&#xff0c;“要促进房地产市…

解决QWidget及内部控件只能放大不能缩小的问题

在设计可缩放控件的时候&#xff0c;你可能会与到这种情况&#xff1a; 缩放 控件只能放大&#xff0c;不能缩小。。。是不是很头痛&#xff1f;让我来猜猜原因&#xff1a;你是不是让子类控件的大小设置地跟父类控件大小一样大&#xff1f;没错这就是原因所在。 用上面一行替换…

pdf怎么盖章不覆盖文字

pdf怎么盖章不覆盖文字&#xff1f;在PDF上盖章而不覆盖文字&#xff0c;可以按照以下步骤操作&#xff1a; 使用福昕PDF编辑器 下载安装&#xff1a;从福昕软件官网下载并安装福昕PDF编辑器。打开文档&#xff1a;用福昕PDF编辑器打开需要盖章的PDF文档。访问图章工具&#…

[网络]抓包工具介绍 tcpdump

一、tcpdump tcpdump是一款基于命令行的网络抓包工具&#xff0c;可以捕获并分析传输到和从网络接口流入和流出的数据包。 1.1 安装 tcpdump 通常已经预装在大多数 Linux 发行版中。如果没有安装&#xff0c;可以使用包管理器 进行安装。例如 Ubuntu&#xff0c;可以使用以下…

Ps:将画板导出到 PDF

菜单&#xff1a;文件/导出/将画板导出到 PDF Export/Artboards to PDF 将画板导出到 PDF Artboards to PDF命令用于将 Photoshop 的画板导出为 PDF 文件&#xff0c;提供了多种导出选项&#xff0c;可以控制文件的压缩、是否嵌入颜色配置文件、文件命名以及页面顺序等。它适用…

电力、电子、电气、电器,怎么说明白?

从学科划分的角度讲 电力、电子和电器都属于电气工程学科。电气工程一词来源于日本&#xff0c;其中的“气”来源于西方外文翻译&#xff08;西方工业之初&#xff0c;动力机械均由蒸汽轮机驱动,后来用与发电&#xff0c;故"电气"开始乏指工业动力&#xff0c;现在电…

高效便捷,体验不一样的韩语翻译神器

嘿&#xff0c;大家好啊&#xff01;今天想跟大家聊聊我用过的几款翻译神器&#xff0c;特别是它们在翻译韩语时的那些小感受。作为一个偶尔需要啃啃韩语资料或者跟韩国朋友聊天的普通人&#xff0c;我真心觉得这些翻译工具简直就是我的救星&#xff01; 一、福昕在线翻译 网址…

Unity网络开发记录(五):二进制传输消息类

消息类 前篇所写的CS模型只能传输字符串&#xff0c;在本篇文章中&#xff0c;尝试在服务端一次传输多种类型的数据&#xff0c;并在客户端接收到信息之后进行解析显示 为了实现对不同类型的数据传输&#xff0c;需要将不同类型的数据都转换成二进制的形式在网络中进行传输。所…

爬虫——爬虫理论+request模块

一、爬虫理论 爬虫——请求网站并提取数据的自动化程序 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟客户端发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动的抓取互联网信息的程序。 原则上&…

通信工程学习:什么是HTTP超文本传输协议

HTTP&#xff1a;超文本传输协议 HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;&#xff0c;即超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络协议&#xff0c;它位于TCP/IP四层模型当中的应用层。以下是关于HTTP协议的详细解释&#xff1a; 一、H…

太速科技-495-定制化仪器户外便携式手提触摸一体机

定制化仪器户外便携式手提触摸一体机 一、产品简介 数据处理便携式机箱平台以mini-ITX主板为基础&#xff0c;集成intel CPU处理器、FPGA、ADDA、光纤等接口&#xff0c;集成触摸显示屏&#xff0c;抗震机箱。设备小型化、一体化&#xff0c;适合实验室、办公桌面、野外…

Cannon-es.js之removeConstraint破坏约束案例

本文目录 前言最终效果1、postStep2、前置准备2.1 代码2.2 效果 3、removeConstraint3.1 解除约束代码效果 4、完整代码 前言 在3D物理引擎的广阔天地中&#xff0c;cannon-es以其轻量级、高性能和易于集成的特点&#xff0c;成为了WebGL环境中物理模拟的首选工具。它不仅能够精…

基于R语言机器学习遥感数据处理与模型空间预测

随机森林作为一种集成学习方法&#xff0c;在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性&#xff0c;随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中&#xff0c;使用Bootstrap抽样生成不同的训练集&#xff…

在海量文档中找资料?5 步打造属于自己的搜索引擎

在海量的文件中寻找那个关键的会议记录&#xff0c;是否让你感到头疼&#xff1f; 想要快速回顾上个月的项目报告&#xff0c;却迷失了一小时都找不到&#xff1f; 找报价、找库存、找供应商&#xff0c;整天忙于各种找找找&#xff1f; 现在就来教大家如何做属于自己的搜索引…

分治法c++

分治法c 快速幂题目算法代码 大整数乘法题目思路代码 快速幂 题目 三个整数 a、b 和 m&#xff0c;计算 a 的 b 次幂对 m 取模的结果ab ac abc(ab)|m(a|mb|m)|m。|为数学中的求模运算符&#xff0c;相当于c语言中的%。(ab)|m(a|mb|m)|m 算法 二分法求幂。先求ab的一半&…