追求对于单调栈的极致理解

追求对于单调栈的极致理解

自己看了好多博客,但是很少有能让我恍然大悟的,都要自己一点一点去琢磨,这是让我深恶痛绝的。

首先先给一道题,单调栈模板:【模板】单调栈 - 洛谷

大意就是给定一个数组,对于数组中的每个元素,求出在它右边的第一个比它大的元素。

直接先入为主,不讲怎么思考从而想到用单调栈解决这个问题的,因为我也想不到。直接讲单调栈是怎么解决的。

最重要的一个点,就是单调栈的状态,在对中间的某一个元素比如x求解的时候,单调栈都是非空的,这里我们假设有n个元素,根据单调栈的定义是单调的,那这个单调的含义到底是什么呢,我感觉这是关键:可以理解为为了对付x这个元素(可以想象为x就是一个人的武力值),我们现在安排了n个元素(也就是我们现在有n个人可以出场),理所当然,先让最弱的人上场(也就是单调),如果最弱的人都比你厉害(也就是比你大),那么就求得答案了(也就是第一个比你大的),如果不厉害,就一直往后走,直到找到一个更厉害的或者栈空(自己最厉害,也就是没有比自己大的元素),最后自己要入栈,因为自己有可能比别人厉害。

其次的一个点,怎么维护栈的状态,如果当前元素(当前人的武力值)比栈顶小,那么就进栈,因为小弟先上,大哥是底牌。。。如果当前元素(当前人的武力值)比栈顶大,那么就要把栈顶的元素拿出来,直到找到比当前元素大的,因为我都比你厉害了,我在后面对付别人的时候(也就是求当前元素前面元素的答案时)我都不行,你比我弱再上场只会浪费时间。

这两个点感觉没有谁先谁后,有点相辅相成的意思。

最后给一个我写的单调栈代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int a[3000005];
int res[3000005];
stack<int> s;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	

	for(int i=n;i>=1;i--){
		while(!s.empty()&&a[i]>=a[s.top()]){
			s.pop();
		}
		if(s.empty()){
			res[i]=0;
		}
		else{
			res[i]=s.top();
		}
		s.push(i);
	}
	for(int i=1;i<=n;i++){
		printf("%d ",res[i]);
	}
}

当然可以看到这个代码有判断栈空的操作,其实可以优化一下,就是在最开始的时候在栈里放入一个哨兵。。也就是直接放一个0,并且令数组中index=0的位置的元素为无穷大(int的最大值),这样如果给定数组中的某一个元素右边没有比它大的元素时,那么就会比较到栈顶为0,即题目规定的0

最后博主也是为了秋招正在刷leetcode,如果大家认为我写的单调栈的确有那种恍然大悟的感觉,可以在评论区说一下,这样以后我碰到好的算法的时候我也会分享一下自己的理解,谢谢各位大哥了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值