栈与单调栈算法主要内容
一、基本思路
1、栈——先入后出
- skt【】 栈数组,tt = 0 为栈顶索引
-
- 插入:skt【++tt】 = x
-
- 弹出:tt–
-
- 判断栈是否为空
-
- tt > 0 非空
-
- tt = 0 空
- tt = 0 空
2、单调栈
- 简介:栈内元素呈单调上升或单调下降
- 问题:给定一个序列,求一下序列中的每一个数。左边 1) 离它最近的 2) 比它小的数在什么地方(也可以求左大、右小、右大在何处),若不存在则返回 -1。
- 暴力做法:
3、单调栈具体实现
- 栈模拟
- 单调栈核心原理:
- 当栈顶元素 >= 遍历元素,则应删除栈顶,从而实现单调
-
1. 循环判断:
-
- 1)栈非空
-
- 2)栈顶元素 >= 新遍历元素
-
- 结果:删掉栈顶
-
2. 若步骤一结束后,栈非空,则栈顶即为单调最近值;否则,输出 -1 。
-
3. 将新元素入栈
二、Java、C语言模板实现
- 模拟栈
- 单调栈
//Java 题解实现
// 模拟栈
import java.util.Scanner;
public class Main {
static int N = 100010;
static int[] skt = new int[N];
static int tt = 0;
public static void push(int x){ // 向栈顶插入一个数
skt[++tt] = x;
}
public static void pop(){ // 从栈顶弹出一个数
tt--;
}
public static void empty(){ // 判断是否为空
if (tt == 0){
System.out.println("YES");
}else {
System.out.println("NO");
}
}
public static void query(){ // 查询栈顶元素
System.out.println(skt[tt]);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int M = scanner.nextInt();
int x;
for (int i = 0; i < M; i++) {
String judge = scanner.next();
switch (judge){
case "push":
x = scanner.nextInt();
push(x);
break;
case "pop":
pop();
break;
case "empty":
empty();
break;
case "query":
query();
break;
}
}
}
}
// 单调栈
import java.util.Scanner;
public class Main {
static int N = 100010;
static int[] stk = new int[N];
static int tt = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int x;
for (int i = 0; i < N; i++) {
x = scanner.nextInt();
while (tt > 0 && stk[tt] >= x){ // 单调栈核心,判断栈顶是否大于等于,若大于等于,则应删掉栈顶,因为求的是最左小
tt--;
}
if (tt == 0) {
System.out.print("-1 "); // 空栈则返回 -1
}else {
System.out.print(stk[tt] + " ");
}
stk[++tt] = x; // 将新元素加入栈顶
}
}
}
```c
// C语言模板实现,此处是yxc实现
// 模拟栈
// tt表示栈顶
int stk[N], tt = 0;
// 向栈顶插入一个数
stk[ ++ tt] = x;
// 从栈顶弹出一个数
tt -- ;
// 栈顶的值
stk[tt];
// 判断栈是否为空,如果 tt > 0,则表示不为空
if (tt > 0)
{
}
// 单调栈
常见模型:找出每个数左边离它最近的比它大/小的数
int tt = 0;
for (int i = 1; i <= n; i ++ )
{
while (tt && check(stk[tt], i)) tt -- ;
stk[ ++ tt] = i;
}