算法竞赛备赛——【数据结构】栈&单调栈

一般应用

P4387 【深基15.习9】验证栈序列 - 洛谷

多组数据记得清空栈

C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;

int main() {
   	int t; cin>>t;
   	while(t--){
   		int n;cin>>n;
		int a[n],b[n];
		for(int i=0;i<n;++i) cin>>a[i];
		for(int i=0;i<n;++i) cin>>b[i];
		stack<int> s;	
		int ai=0,bi=0;
		while(ai<n){
			s.push(a[ai]);
			while(!s.empty()&&s.top()==b[bi]){
				s.pop();
				bi++;
			}
			ai++;
		}
		if(bi==n) cout<<"Yes\n";
		else cout<<"No\n";
   	} 
	return 0;
}

735. 小行星碰撞 - 力扣(LeetCode)

C++ 复制代码
class Solution {
public:
    vector<int> asteroidCollision(vector<int>& asteroids) {
        vector<int> s;
        int n=asteroids.size();
        for(int i=0;i<n;i++){
            if(asteroids[i]>0||s.size()==0){
               s.push_back(asteroids[i]);
            }else{
               while(s.size()!=0&&s.back()>0&&s.back()<-asteroids[i]){
                    s.pop_back();
               }
               if(s.size()==0||s.back()<0){
                    s.push_back(asteroids[i]);
               } 
               else if(s.back()==-asteroids[i]){
                    s.pop_back();
               }
            }
        }
        return s;
    }
};

单调栈

栈中的元素是严格单调递增或者递减的,也就是说:从栈底到栈顶,元素的值逐渐增大或者减小。

要描述清楚如何增大:从底向顶递增从顶向底递增

  • 解决问题:

向左/右找第一个比自身大/小的数。

元素间大小判断:对于当前遍历到的数,栈顶为答案。

1.向左找第一个比自己大的数。左--->右 底到顶递减栈

2.向左找第一个比自己小的数。左--->右 底到顶递增栈

3.向右找第一个比自己大的数。右--->左 底到顶递减栈

4.向右找第一个比自己小的数。右--->左 底到顶递增栈

这个方法更简单

  • 模板
C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e3+5;
 
int n;
int a[N];
stack<int> s;
int ans[N];//ans[i]就是a[i]左边第一个比a[i]大的数
 
//向左找第一个比自己大的数。左--->右 底到顶递减栈

int main() {
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}   	
	for(int i=1;i<=n;++i){
		//栈非空并且当前栈顶小于a[i]  连续出栈
		while(!s.empty()&&s.top()<=a[i]){
			s.pop();
		} 
		
		//栈可能为空
		if(s.empty()){
			ans[i]=-1;
		} else{
			ans[i]=s.top();
		}
		s.push(a[i]);//入栈时记录答案 
	}
	for(int i=1;i<=n;++i){
		cout<<ans[i]<<" ";
	}
	return 0;
}

元素间大小判断:对于栈顶,当前遍历到的数为答案。

1.向左找第一个比自己大的数。右--->左 底到顶递减栈

2.向左找第一个比自己小的数。右--->左 底到顶递增栈

3.向右找第一个比自己大的数。左--->右底到顶递减栈

4.向右找第一个比自己小的数。左--->右底到顶递增栈

这个方法稍微复杂

  • 模板
C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e3+5;
 
int n;
int a[N];
stack<int> s;
int ans[N];//ans[i]就是a[i]左边第一个比a[i]大的数
 
//向左找第一个比自己大的数。右--->左 底到顶递减栈

int main() {
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}   	
	//下标入栈 
	for(int i=n;i>=1;--i){
		//栈非空并且当前栈顶小于a[i] 
		while(!s.empty()&&a[s.top()]<a[i]){
			ans[s.top()]=a[i];
			s.pop();
		} 
		s.push(i); 
	}
	//剩下的是左边无比他大的数 
	while(!s.empty()){
		ans[s.top()]=-1;
		s.pop();
	} 
	for(int i=1;i<=n;++i){
		cout<<ans[i]<<" ";
	}
	return 0;
}

P5788 【模板】单调栈 - 洛谷

C++ 复制代码
#include <bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e7+5;
 
int n;
int a[N];
stack<int> s;
int ans[N];

int main() {
	cin>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}   	
	for(int i=n;i>=1;--i){//从右往左
		while(!s.empty()&&a[s.top()]<=a[i]){//<=!
			s.pop();
		}
		if(s.empty()){
			s.push(i);
			ans[i]=0;
		}
		else{
			ans[i]=s.top();
			s.push(i); 
		} 
	} 
	for(int i=1;i<=n;++i){
		cout<<ans[i]<<" ";
	}
	return 0;
}

42. 接雨水 - 力扣(LeetCode)

C++ 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        stack<int> s;
        int ans=0;
        for(int i=0;i<n;++i){
            while(!s.empty()&&height[s.top()]<height[i]){
                int b=s.top();//凹槽底部
                s.pop();
                if(!s.empty()){//新的栈顶是凹槽的左边柱子
                    int h=min(height[i],height[s.top()])-height[b];//水量的高度
                    int w=i-s.top()-1;//宽度
                    ans+=w*h;
                }
            }
            s.push(i);//入栈
        } 
        return ans;
    }
};
相关推荐
Jack电子实验室7 分钟前
STM32实现智能温控系统(暖手宝):PID 算法 + DS18B20+OLED 显示,[学习 PID 优质项目]
stm32·学习·算法
KangkangLoveNLP8 分钟前
从概率到梯度:理解分类问题中交叉熵的优越性
人工智能·深度学习·算法·机器学习·分类·lstm·transformer
围巾哥萧尘27 分钟前
「原型设计」Trae AI & DeepSeek-Chat-V3 在微信小程序「倒计时」原型中的复现🧣
算法·ios·架构
高山莫衣31 分钟前
【差分隐私相关概念】约束下的矩阵机制
线性代数·算法·矩阵
十五年专注C++开发35 分钟前
双指针技巧在C++中的应用:从基础到进阶
开发语言·数据结构·c++
aimmon1 小时前
Rust从入门到精通之精通篇:24.高级异步编程
开发语言·算法·rust
小学仔1 小时前
### Java二维字符矩阵输入解析:正确读取由0和1组成的矩阵
java·算法·leetcode·矩阵·动态规划
每天敲200行代码1 小时前
Linux 多线程-生产消费者模型&线程池&线程单例模式&其他
linux·c++·单例模式·线程池·生产消费者模型
菜鸟00881 小时前
蓝桥杯 第十天 2019国赛第4题 矩阵计数
算法·职场和发展·蓝桥杯
LinkerLin1 小时前
因果推理的智慧:当大模型遇见因果图谱
算法