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

栈

一般应用

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;
    }
};
相关推荐
HRTOS3 分钟前
HRTOS 内核 BUG 修复:任务等待对象未初始化导致的异常唤醒问题
单片机·嵌入式硬件·算法·51单片机
瑶山10 分钟前
Windows + WSL2 Ubuntu + VS Code配置C++开发环境
开发语言·c++·windows·vscode·wsl
XMAIPC_Robot17 分钟前
国产FPGA替代Xilinx在储能电力采集场景可行性评估与移植经验
人工智能·算法·机器学习·fpga开发·rk3588+fpga
开开心心就好22 分钟前
一元二次方程求解工具,答案带详细步骤
java·服务器·开发语言·算法·pdf·ocr·perl
aqiu11111124 分钟前
蓝桥杯省一学习计划:每天 2 小时,12 周高效备赛
学习·职场和发展·蓝桥杯
小米里的大麦31 分钟前
19 C、C++ 操作 MySQL
c语言·c++·mysql
有毒的教程43 分钟前
Dev-C++ 使用扩展库两种方式:DevPak一键安装 / 手动配置(重点)
android·c++·adb
Logic10144 分钟前
C语言/数据结构位运算题解:异或XOR找出套碗游戏中的“幸运碗“——只出现一次的数字
c语言·数据结构·算法·数组·位运算·时间复杂度·空间复杂度
纪念 2291 小时前
c++ string(二)
开发语言·c++
sanqima1 小时前
MFC里的线程本地存储(TLS)与模块状态(Module State)
c++·mfc·tls·module state