单调栈(单调递减栈,单调递增栈)

单调栈:一种特殊的栈。在栈的「先进后出」规则基础上,要求「从 栈顶栈底 的元素是单调递增(或者单调递减)」。其中满足从栈顶到栈底的元素是单调递增的栈,叫做「单调递增栈」。满足从栈顶到栈底的元素是单调递减的栈,叫做「单调递减栈」

1.单调递增栈

单调递增栈:只有比栈顶元素小的元素才能直接进栈,否则需要先将栈中比当前元素小的元素出栈,再将当前元素入栈。

这样就保证了:栈中保留的都是比当前入栈元素大的值,并且从栈顶到栈底的元素值是单调递增的。

单调递增栈的入栈、出栈过程如下:

假设当前进栈元素为 x,如果 x 比栈顶元素小,则直接入栈。

否则从栈顶开始遍历栈中元素,把小于 x 或者等于 x 的元素弹出栈,直到遇到一个大于 x 的元素为止,然后再把 x 压入栈中。栈内元素为下标

单调栈例题 :【模板】单调栈 - 洛谷

#include<iostream>
#include<stack>
using namespace std;
#define ll long long
const int N=3e6+5;
ll a[N],s1[N];
int main(){
   stack<ll> s;
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)
  cin>>a[i];
  for(int i=n;i>0;i--){
  while(!s.empty()&&a[s.top()]<=a[i])
        s.pop(); // <=是因为题目要求是第 i个元素后
  if(s.empty()) s1[i]=0; //第一个大于a[i]的数
  else s1[i]=s.top(); //因为我们是从后往前遍历的,所以如果等于的话也要弹出
  s.push(i); //小于栈顶元素直接入栈
}
  for(int i=1;i<=n;i++)
   cout<<s1[i]<<" ";
   cout<<endl;
}

如果插入时的栈为空,则说明右侧不存在比当前元素大的元素,就先存入栈中。如果后面有比当前元素大的,就把栈顶元素删除,把当前元素的下标入栈;如果比栈顶元素小就直接入栈,每次记录当前栈顶的值就为第一个大于 a[i]的值的下标,如果该元素没有被弹出栈,则说明右侧不存在比当前元素大的元素。

2.单调递减栈

单调递减栈:只有比栈顶元素大的元素才能直接进栈,否则需要先将栈中比当前元素大的元素出栈,再将当前元素入栈。

这样就保证了:栈中保留的都是比当前入栈元素小的值,并且从栈顶到栈底的元素值是单调递减的。

单调递减栈的入栈、出栈过程如下:

  • 假设当前进栈元素为 x,如果 x 比栈顶元素大,则直接入栈。

  • 否则从栈顶开始遍历栈中元素,把大于 x 或者等于 x 的元素弹出栈,直到遇到一个小于 x 的元素为止,然后再把 x 压入栈中。

#include<iostream>
#include<stack>
using namespace std;
#define ll long long
const int N=3e6+5;
ll a[N],s1[N];
int main(){
   stack<ll> s;
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)
  cin>>a[i];
  for(int i=n;i>0;i--){
  while(!s.empty()&&a[s.top()]>=a[i])
        s.pop(); 
  if(s.empty()) s1[i]=0; //第一个小a[i]的数
  else s1[i]=s.top(); //因为我们是从后往前遍历的,所以如果等于的话也要弹出
  s.push(i); //大于栈顶元素直接入栈
}
  for(int i=1;i<=n;i++)
   cout<<s1[i]<<" ";
   cout<<endl;
}

如果插入时的栈为空,则说明右侧不存在比当前元素小的元素,就先存入栈中。如果后面有比当前元素小的,就把栈顶元素删除,把当前元素的下标入栈;如果比栈顶元素大就直接入栈,每次记录当前栈顶的值就为右侧第一个小于 a[i]的值的下标,如果该元素没有被弹出栈,则说明右侧不存在比当前元素小的元素。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,单调栈单调队列是两种不同的数据结构单调栈是一个,它的特点是内的元素是单调的,可以是递增递减的。在构建单调栈时,元素的插入和弹出都是在的一端进行的。与此类似,单调队列也是一个队列,它的特点是队列内的元素是单调的,可以是递增递减的。在构建单调队列时,元素的插入是在队列的一端进行的,而弹出则是选择队列头进行的。 单调队列在解决某些问题时,能够提升效率。例如,滑动窗口最大值问题可以通过使用单调队列来解决。单调队列的结构可以通过以下代码来实现: ```python class MQueue: def __init__(self): self.queue = [] def push(self, value): while self.queue and self.queue[-1 < value: self.queue.pop(-1) self.queue.append(value) def pop(self): if self.queue: return self.queue.pop(0) ``` 上述代码定义了一个名为MQueue的类,它包含一个列表作为队列的存储结构。该类有两个方法,push和pop。push方法用于向队列中插入元素,它会删除队列尾部小于插入元素的所有元素,并将插入元素添加到队列尾部。pop方法用于弹出队列的头部元素。 总结来说,单调栈单调队列都是为了解决特定问题而设计的数据结构单调栈在构建时元素的插入和弹出都是在的一端进行的,而单调队列则是在队列的一端进行的。在Python中,可以通过自定义类来实现单调队列的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值