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

一般应用

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;
    }
};
相关推荐
chuhx32 分钟前
Stream API 对两个 List 进行去重操作
数据结构·windows·list
元亓亓亓3 小时前
Java后端开发day36--源码解析:HashMap
java·开发语言·数据结构
小邓儿◑.◑4 小时前
C++武功秘籍 | 入门知识点
开发语言·c++
酷ku的森5 小时前
数据结构:链表
数据结构·链表
何其有幸.6 小时前
实验3-3 比较大小(PTA|C语言)
c语言·数据结构·算法
丶Darling.6 小时前
26考研 | 王道 | 数据结构笔记博客总结
数据结构·笔记·考研
杨筱毅6 小时前
【优秀三方库研读】【C++基础知识】odygrd/quill -- 折叠表达式
c++·三方库研读
东阳马生架构7 小时前
Sentinel源码—8.限流算法和设计模式总结二
算法·设计模式·sentinel
老饼讲解-BP神经网络7 小时前
一篇入门之-评分卡变量分箱(卡方分箱、决策树分箱、KS分箱等)实操例子
算法·决策树·机器学习
hjjdebug7 小时前
c++中的enum变量 和 constexpr说明符
c++·enum·constexpr