这篇文章是看了“左程云”老师在b站上的讲解之后写的, 自己感觉已经能理解这个题目了, 所以就将整个过程写下来了。
这个是“左程云”老师个人空间的b站的链接, 数据结构与算法讲的很好很好, 希望大家可以多多支持左程云老师, 真心推荐.
https://space.bilibili.com/8888480?spm_id_from=333.999.0.0
顺便提供一下测试链接:
https://leetcode.cn/problems/min-stack/
1. 逻辑结构实现
- 我们需要设置两个
栈
, 一个栈
是data栈
, 另一个栈
是min栈
,data栈
是用来存放所有存入的数据的,min栈
是用来存放所有放入的数据的过程中最小的数据的. - 如何使用这两个
栈
, 有三种情况:(注意看题目要求:最小值是data栈
中剩下的数据中最小的值.)- 若是第一次放入数据, 直接将这个“数据”同时放入这两个
栈
. - 若是
新放入的数据 <= min栈栈顶元素
, 就将这个“数据”同时放入data栈 和 min栈
. - 若是
新放入的数据 > min栈栈顶元素
, 就将这个“数据”放入data栈
, 但是放入min栈
中的是min栈中的栈顶元素
.
- 若是第一次放入数据, 直接将这个“数据”同时放入这两个
- 这样的实现, 无论怎么进行弹出,
min栈
中的栈顶元素一定是data栈中
数据的最小值.
过程如下图:自己画图实现一下就理解了.
2. 代码实现
2.1 第一种方式
关于每一个方法的实现, 我都在对应的地方写上了注释, 应该是能看懂, 过程也在逻辑结构分析的地方写清楚了.
注意:因为这个实现方式使用的是 JDK
中自带的栈, 所以常数时间不是很好, 第二种直接使用 数组
, 这样就比较快.
// 提交时把类名、构造方法改成MinStack
class MinStack1 {
public Stack<Integer> data;
public Stack<Integer> min;
public MinStack1() {
data = new Stack<Integer>();
min = new Stack<Integer>(); // 使用JDK自带的栈.
}
public void push(int val) {
data.push(val); // 不管怎么样, data栈是一定要放入的.
if (min.isEmpty() || val <= min.peek()) { // 当“min栈”为“空”的时候, 或者“放进来的数字” <= “min栈栈顶元素”
min.push(val); // 将“放进来的数据放入min栈”.
} else { // !min.isEmpty() && val > min.peek() // 若是反过来, min不为“空”, 并且“放进来的数字” > “min栈栈顶元素”
min.push(min.peek()); // 将“min栈栈顶元素放入min栈”.
}
}
public void pop() { // 弹出就将两个栈的栈顶元素同时弹出,
data.pop(); // 因为题目需要的是“data栈中”剩下的数据中最小的.
min.pop();
}
public int top() {
return data.peek();
}
public int getMin() {
return min.peek(); // “min栈”中栈顶元素一定是“data栈”剩下的数据中最小的.
}
}
2.2 第二种方式
这个和上面的原理是一模一样的, 就是实现栈的时候使用的是自己制作的 数组
, 基本上没什么可讲的, 甚至注释可以直接照搬下来, 所以这里就不再多此一举, 再抄一遍注释, 而且第二种方式用数组的时候需要开多大, 左程云老师的代码注释里写了, 也就不多说了.
// 提交时把类名、构造方法改成MinStack
class MinStack2 {
// leetcode的数据在测试时,同时在栈里的数据不超过这个值
// 这是几次提交实验出来的,哈哈
// 如果leetcode补测试数据了,超过这个量导致出错,就调大
public final int MAXN = 8001;
public int[] data;
public int[] min;
int size;
public MinStack2() {
data = new int[MAXN];
min = new int[MAXN];
size = 0; // 数组的长度大小
}
public void push(int val) {
data[size] = val;
if (size == 0 || val <= min[size - 1]) {
min[size] = val;
} else {
min[size] = min[size - 1];
}
size++;
}
public void pop() {
size--;
}
public int top() {
return data[size - 1];
}
public int getMin() {
return min[size - 1];
}
}