[带自己学/复习算法] 1.单调栈

单调栈

单调栈是一种特殊的栈,其栈内元素共有4种情况:单调增不增不减
其常与一个经典问题相联系使用:专注于一个数组中的第 i i i 个元素,找左右两边第一个小于大于不小于不大于的元素下标和值。
当需要找左边第一个满足条件的元素时,需要正向遍历。右边则需要反向遍历。

以一个常见的问题举例:柱状图中最大的矩形
看到问题首先进行分析,面积由长 * 宽两部分计算,而宽显然是 h [ i ] h[i] h[i],长也显然是两端能延伸的最大长度。很容易想到这与找一个元素左右第一个小于的下标等价。
下面给出代码中单调栈的实现及解释:

# 仅为部分代码,只实现了找左侧第一个小于的元素
# 举的例子中,一律默认 栈底-[]-栈顶
stack<int>stk(n); # 单调栈,栈中存储的是下标,值可以通过h[下标]来访问
vector<int>pre(n); # pre[i] 代表 第i个元素 左侧的第一个满足要求的元素下标
for(int i=0;i<n;i++){
    while(stk.size() and !(h[stk.top()] < h[i])){
    	
     	# 此处判断的是,新来的元素若要加入时,栈不满足单调性,则需要不断弹出其中的元素。
     	# 直至加入后可以满足原来的单调性为止
     	# 举个例子: [1,2,4,5]
     	# 若新来的元素为3,加入后[1,2,4,5,3]显然不满足原来的单调增
     	# 于是不断弹出元素 直至为 [1,2]时,3加入才能满足单调性
     	
    	# 当单调栈非空 且 栈顶代表的元素值 不小于 当前要新加入的元素时
        stk.pop();
    }
    # 更新pre数组,若单调栈此时不为空,则栈顶一定是左侧第一个小于的元素
    # 要取满足题意的,只需要取栈顶下标的右边一位即可
    
    pre[i] = stk.size() ? stk.top() + 1 : 0;
    # 然后把元素入栈
    stk.push(i);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值