算法学习Day1——【数据结构】单调栈

news/2024/9/24 18:53:25/

1.什么是单调栈以及单调栈的作用

(1)定义

顾名思义,单调栈是一个有序的栈,可能从栈顶到栈底单调递增(单调递增栈),也有可能从栈顶到栈底单调递减(单调递减栈)

(2)用途

单调栈可以在时间复杂度为 O(n)$的情况下,求解出某个元素左边或者右边第一个比它大或者小的元素。

所以单调栈一般用于解决一下几种问题:

1.寻找左侧第一个比当前元素大的元素。

2.寻找左侧第一个比当前元素小的元素。

3.寻找右侧第一个比当前元素大的元素。

4.寻找右侧第一个比当前元素小的元素。

那么我们在这里进行对上述四种问题进行阐述,

1.寻找左侧第一个比当前元素大的元素,我们可以创建一个单调递增栈,把我们这个元素与栈顶元素进行比较,如果栈顶元素小于要该元素,那么直接将栈顶元素弹出,然后继续比较,直到找到第一个比这个元素大的元素,或者说栈为空,如果栈为空,那么说明左边不存在比这个元素更大的元素了

2.寻找左侧第一个比当前元素小的元素,我们创建一个单调递减栈,将这个栈顶元素和该元素进行比较,如果该项元素大于栈顶元素,那么就要将该元素插入,并且此时的栈顶元素就是左侧第一个比该元素小的元素

3.寻找右侧第一个比当前元素大的元素,我们创建一个单调递增栈,然后从左向右遍历,第一个将这个元素从栈中弹出的元素就是右侧第一个比这个元素大的

4.寻找右侧第一个比当前元素小的元素,我们要创建单调递减栈,然后从左向右遍历,就是第一个将该元素从栈中弹出的就是右侧第一个比这个元素小的

(3)伪代码

stack<int> st;
//此处一般需要给数组最后添加结束标志符,具体下面例题会有详细讲解
for (遍历这个数组)
{if (栈空 || 栈顶元素大于等于当前比较元素){入栈;}else{while (栈不为空 && 栈顶元素小于当前元素){栈顶元素出栈;更新结果;}当前数据入栈;}
}

2.相关例题

1.模版单调栈 

纯模版题,没啥可说的,记得往栈里面存的是结构体就行 

#include<bits/stdc++.h>
using namespace std;
int n;int f[3000005];
struct node
{int w;int flag;
}a[3000005];
stack<node> q;
int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i].w;a[i].flag=i;}for(int i=1;i<=n;i++){while(!q.empty()&&a[q.top().flag].w<a[i].w){f[q.top().flag]=i;q.pop();}q.push(a[i]);}for(int i=1;i<=n;i++){printf("%d ",f[i]);}
}

 2.Look Up S

和上面的题一个板子

#include<bits/stdc++.h>
using namespace std;
int n;
struct node{int h;int flag;
}a[100005];
int f[100005];
stack<node> q;
int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i].h;a[i].flag=i;}for(int i=1;i<=n;i++){while(!q.empty()&&q.top().h<a[i].h){f[q.top().flag]=i;q.pop();}q.push(a[i]);}for(int i=1;i<=n;i++){printf("%d\n",f[i]);}
}

3. 求数列所有后缀最大值的位置

 

这题两个知识点,一个是异或操作,另一个是单调栈

#include<bits/stdc++.h>
using namespace std;struct node{unsigned long long w;int flag;
}a[1000005];
int n;
long long sum;
stack<node> q;
int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i].w;a[i].flag=i;}for(int i=1;i<=n;i++){while(!q.empty()&&q.top().w<a[i].w){sum^=q.top().flag;q.pop();}q.push(a[i]);sum^=q.top().flag;printf("%lld\n",sum);}return 0;
} 

 


http://www.ppmy.cn/news/1451290.html

相关文章

一些不错的技术网站(持续更新)

嵌入式&#xff1a; GitHub - nhivp/Awesome-Embedded: A curated list of awesome embedded programming. 求职&#xff1a; https://www.toutiao.com/w/1782514534500489/?appnews_article&timestamp1699951341&use_new_style1&share_tokenA6AADF47-C6E0-4EF3…

java的嵌套循环

在java中&#xff0c;也有嵌套循环。 下面是一个示例代码 public class Example17qiantaoxunhuan {public static void main(String[] args) {int i,j;for(i1;i<9;i){for(j1;j<i;j){System.out.println("*");}System.out.println("\n");}}}这段代码…

在Mac上使用国内源安装 homebrew

打开终端&#xff0c;执行如下指令 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"还原官网地址 git -C "/opt/homebrew" remote set-url origin https://github.com/Homebrew/brew查看版本 brew -v查找软件…

你不需要总是在 React 中使用 useState

在我审查的一个拉取请求中&#xff0c;我注意到在许多拉取请求中看到的一种模式。React 组件具有多个 UI 状态&#xff0c;例如 loading、error 和 success。 作者使用了多个 useState 钩子来管理这些状态&#xff0c;这导致代码难以阅读且容易出错&#xff0c;例如&#xff1a…

低代码工业组态数字孪生平台

2024 两会热词「新质生产力」凭借其主要特征——高科技、高效能及高质量&#xff0c;引发各界关注。在探索构建新质生产力的重要议题中&#xff0c;数据要素被视为土地、劳动力、资本和技术之后的第五大生产要素。数据要素赋能新质生产力发展主要体现为&#xff1a;生产力由生产…

Linux / Ubuntu 备份数据

Linux / Ubuntu 备份数据 需要备份的文件tar 工具备份/打包过程恢复/解包过程 流程自动化start_backup.shserver_backup.sh 同步发布在个人笔记Linux / Ubuntu 备份数据 需要备份的文件 对于我们的 linux 服务器&#xff08;当然也适用于桌面端&#xff09;&#xff0c;时常进…

LeetCode 131 —— 分割回文串

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 首先&#xff0c;按照 LeetCode 5——最长回文子串 中的思路&#xff0c;我们先求出 d p dp dp&#xff0c;这样我们就知道了所有的子串是否是回文子串。 然后&#xff0c;我们进行一个 dfs 搜索&#xff0c;起…

(汇总)vue中在不同页面之间-4种传递参数的方式

Vue项目页面间传递参数和参数存储有很多种&#xff0c;常见的&#xff1a; &#xff08;参考链接&#xff1a;www.qinglite.cn/doc/4603647… url里加参数&#xff0c;比如&#xff1a;/find?idxxx&#xff0c;或/find/xxx&#xff0c;适合少量数据&#xff0c;优点是刷新页面…