单调栈问题

单调栈问题

提起单调栈,有一个很经典的问题:找出一串数字中任意一个数字左/右边最近的比该数小的数字。比如:有一串数字8 4 3 7 9 5,我们需要得到其中任意一个数字左边最近的比该数还要小的数字,那么对于这串数字我们返回的数字为-1 -1 -1 3 7 3。

最朴素的做法就是双重循环,第一重循环遍历每个数字,第二重循环遍历这个数字左边的数字,找出最近的比该数小的数字。

那么,单调栈是什么?我们如何用单调栈来解决此类问题?
数字有序地存储在栈中,单调栈有两种,一是单调递增栈,二是单调递减栈。
单调递增栈就是从栈底到栈顶数字由大变小。
单调递减栈就是从栈顶到栈底数字由大变小。

对于该题,当我们寻找7这个数字左边最近的比7小的数字的时候,我们可以把7前面的数字依次入栈,如果出现后入栈的数字比先入栈的数字小的情况,那么先入栈的数字将会被删掉。经过这些删除操作之后,栈中的数字呈现一种递增的趋势,这个时候我们去找离7这个数字最近的比7小的数就很容易了。
下面是参考y总算法基础课中的部分代码实现:

#include <iostream>
using namespace std;
const int N = 10010;
int main(){
	int stk[N],tt;
	int n;
	cin>>n;
	for(int i = 0;i<n;i++)
	{
		int x;
		cin>>x;
		while(tt&&stk[tt]>=x) tt--;//删除比x还要大的数字并且如果栈中有两个元素都比x小,前面的数比后面的数大,那么毫无疑问前面的数字也需要删掉,因为前面的数也根本用不着。
		if(tt) cout<<stk[tt]<<' ';//输出最近的比该数小的数
		else cout<<"-1"<<' ';//左边没有比该数小的
		
		stk[++tt]=x;//将当前元素添加到栈中
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值