【算法学习之路】9.单调栈

栈和队列

  • 前言
  • 一.简介
  • 二.操作(以底到顶递增为例)
  • 三.元素大小判断(以底到顶递增为例)
  • 四.单调栈的应用
    • 1
    • 2

前言

我会将一些常用的算法以及对应的题单给写完,形成一套完整的算法体系,以及大量的各个难度的题目,目前算法也写了几篇,题单正在更新,其他的也会陆陆续续的更新,希望大家点赞收藏我会尽快更新的!!!

一.简介

单调栈的元素是严格单调递增和递减也就是说从栈底到栈顶元素的值逐渐增大或减小,多用于求解元素的左右大小边界问题:
如:
找左边第一个比自身大的数
找左边第一个比自身小的数
找右边第一个比自身大的数
找右边第一个比自身小的数

二.操作(以底到顶递增为例)

1.如果新的元素比栈顶元素大就入栈
2.如果新的元素比栈顶元素小,那就一直把栈内元素弹出来,直到栈顶比新元素小

三.元素大小判断(以底到顶递增为例)

1.当栈中已有元素需要出栈,说明后续这个元素是需要出栈的元素向后找第一个比其小的元素
2.当元素出栈后新栈顶元素向前找第一个比其小的
3.一般栈内记录元素的下标通过a[i]找到元素

四.单调栈的应用

1

洛谷P5788 【模板】单调栈
【算法学习之路】9.单调栈_第1张图片
从后往前扫,对于每个元素:
1.弹出栈顶比她小的元素
2.此时栈顶就是答案(放到一个数组)
3.加入这个元素由于是从前往后输出答案数组

#include 
#include 
using namespace std;
int a[3000005], b[3000005];//a:存数据,b:存答案
stack<int> s;//存下标
int main() {
	int n; cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	//因为要看后面数据是否大于前面的数据,所以从后往前输出
	for (int i = n; i >= 1; i--) {
		while (!s.empty() && a[s.top()] <= a[i]) {//如果栈不空且其数据小于后面的数据
			s.pop();//将该数据弹出
		}
		b[i] = (s.empty() == 1) ? 0 : s.top();//如果为空就存0,否则存栈的元素
		s.push(i);//将该下标入栈
	}
	for (int i = 1; i <= n; i++) {
		printf("%d ", b[i]);
	}

	return 0;
}

2

力扣42. 接雨水
【算法学习之路】9.单调栈_第2张图片
当枚举的将要入栈的元素大于栈顶时,说明出现了凹槽,计算该凹槽的蓄水量:
例如:
栈内元素:2 1,3要入栈,3比栈顶大,出现了凹槽。凹槽右边是将入栈的元素,左边是栈顶向下第一个大于栈顶的元素。
怎么计算蓄水量:
高*宽。宽是下标的差值,高是下标对应的元素值。 所以栈中存下标。
所以:
将要入栈的元素大于栈顶下标对应的元素时 ,说明出现了凹槽。此时将栈顶记录下来之后,不断出栈,直到新的栈 顶大于旧栈顶。
记:
新栈顶为ntop,旧栈顶为top,将入栈的下标为i, 则:宽= i-top-1 =min(h[ntop],h[i])-h[top]。

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> s;//定义一个栈,用来存下标
        int n = height.size();//查找有多少元素
        int sum = 0;//接雨水总数
        for(int i = 0; i < n; i++){
            if(s.empty()){//检查是否为空
                s.push(i);
            }
            else{
                while(!s.empty() && height[s.top()] < height[i]){//如果不为空且比栈中的大
                    int x = s.top();
                    s.pop();
                    if(!s.empty()){//要检查是否为空
                        int h = min(height[i], height[s.top()]) - height[x];//计算高度
                        int w = i - s.top() - 1;//计算宽度
                        sum += h * w;
                    }
                }
                s.push(i);//将元素入栈
            }
        }
        return sum;
    }
};

你可能感兴趣的:(算法学习之路,算法,学习,c++,开发语言,单调栈,数据结构)