数据结构_栈和单调栈

Posted hot-machine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构_栈和单调栈相关的知识,希望对你有一定的参考价值。

数组模拟栈

代码模板

const int N = 1e6 + 10;
int st[N], tt = -1;

void push(int x) {
    st[++tt] = x;
}

void pop() {
    --tt;
}

bool isempty() {
    return  tt >= 0;
}

void query() {
    cout << st[tt] << endl;
}

单调栈

  • 题目描述1: 给定一个长度为N的整数数列,输出每个数++左边++++第一个比它小的数++,如果不存在则输出-1。

暴力做法(TLE):双指针算法

void solve() {
    for(int i = 0; i < n; i++) {
        int j = i - 1;
        while(j != -1 && st[j] > a[i]) j--;
        if(j) printf("%d ", st[j]);
        else printf("-1 ");
    }
}

单调栈

思路分析:

  • 假设i < j, 而且a[i] > a[j], 如果a[i]满足条件,则a[j]也必然满足条件。
  • 题目要求输出每个数左边第一个比它小的数,因此输出a[j], 而a[i]一定不会用到。
  • 由此可以得出一个规律:在这个题中,只要存在以下这种情况:
i < j

a[i] > a[j]
  • 即下标小,而其数值反而大的情况一定不会采用。
  • 因此我们完全可以不考虑这种数,而把有用的数单独存储起来,可以选择栈这种数据结构
  • 而最终我们得到的栈中的元素都满足这样的规律:单调性
i < j

a[i] < a[j]

代码模板

const int N = 1e6 + 10;
int st[N], tt = 0;
void solve() {
    for(int i = 0; i < n; i++) {
        while(tt && st[tt] >= a[i]) tt--;
        if(tt) printf("%d ", st[tt]);
        else printf("-1 ");
        st[++tt] = a[i];
    }
}
  • 题目描述2:数列中第 i 个元素之后第一个大于a[i]的元素的下标
const int N = 3e6 + 10; // 根据题目数据范围
int st[N], a[N], ans[N], tt = 0; // 数组模拟的栈从下标为1开始存储

void solve() {
	int n; scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for(int i = n; i >= 1; i--) {
		while(tt && a[st[tt]] <= a[i]) tt -- ; // 删去比当前位置的数小的,剩下第一个比当前的数大的
		ans[i] = (tt) ? st[tt]: 0;
		st[++tt] = i;
	}
	for(int i = 0; i < n; i++) printf("%d ", ans[i]);
}

以上是关于数据结构_栈和单调栈的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode- 柱状图中最大的矩形(单调栈)

考研数据结构与算法栈和队列

单调队列与单调栈用法详解

数据结构_第六关:栈和队列(栈)

poj2796(单调栈+树状数组)

单调栈 队列学习