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

一般应用

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;
    }
};
相关推荐
青草地溪水旁23 分钟前
C++中的Reactor和Proactor模型进行系统性解析
c++·网络编程‘
AMiner:AI科研助手28 分钟前
警惕!你和ChatGPT的对话,可能正在制造分布式妄想
人工智能·分布式·算法·chatgpt·deepseek
深耕AI3 小时前
【MFC中OnInitDialog虚函数详解:哪个是虚函数?两个OnInitDialog的关系】
c++·mfc
CHANG_THE_WORLD4 小时前
并发编程指南 同步操作与强制排序
开发语言·c++·算法
pl00204 小时前
C++虚函数&虚析构函数&纯虚函数的使用说明和理解
c++·虚函数·纯虚函数·虚析构函数
gaoshou455 小时前
代码随想录训练营第三十一天|LeetCode56.合并区间、LeetCode738.单调递增的数字
数据结构·算法
自信的小螺丝钉5 小时前
Leetcode 240. 搜索二维矩阵 II 矩阵 / 二分
算法·leetcode·矩阵
闪电麦坤955 小时前
数据结构:深度优先搜索 (Depth-First Search, DFS)
数据结构·深度优先
KING BOB!!!6 小时前
Leetcode高频 SQL 50 题(基础版)题目记录
sql·mysql·算法·leetcode
小wanga7 小时前
C++知识
java·开发语言·c++