例题:
分析:
题目要求我们必须在常数时间内检索到最小元素。
我们可以使用两个栈(A、B)来实现,A栈用来正常存储数据、弹出数据, B栈用于存储A栈中的最小元素,如下图:
刚开始, A栈没有数据, B栈先储存一个元素MAX(整数最大值)。
添加元素时:
当向栈中加入数据时,比如先加入元素 2 , 在A栈中直接存入 2, 同时新加入元素与 B栈的栈顶元素比较,把较小值加入B栈。保证在每次加入元素后,B栈的栈顶是本次的最小元素。
弹出元素时:
当弹出元素时,A栈正常弹出元素,同时B栈也要弹出元素
代码实现:
package leetcodeup;
import java.util.LinkedList;
public class MinStackLeetcode155 {
static class MinStack {
private final LinkedList<Integer> stack = new LinkedList<>();
private final LinkedList<Integer> min = new LinkedList<>();
public MinStack() {
min.push(Integer.MAX_VALUE);
}
public void push(int val) {
stack.push(val);
min.push(Math.min(val, min.peek()));
}
public void pop() {
if(stack.isEmpty()){
return;
}
stack.pop();
min.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return min.peek();
}
}
}
这是求解这道题的第一种方法。
第二种方法:
其实和第一种方法思路差不多,我们可以把新添加元素和栈里面的最小元素一起加入栈中,这样我们可以少用一个栈的空间。如下图:
要存储这样的数据我们可以使用一种特殊的数据类型, --> record ,它是JDK16引用的新语法,
record
是一种新的关键字,用于创建不可变的(immutable)数据类,使用 record
关键字可以简化数据类的编写,并自动提供许多常见的方法,如 equals()
, hashCode()
, toString()
等。
record Data(int val, int min){
}
在上面的代码中,我们定义了一个名为 Data的记录类,它有两个字段 val和 min。由于这是一个 record
,Java 会自动为这个类生成 equals()
, hashCode()
, toString()
, 和一个构造函数。并为两个字段生成对应的get、set方法。
代码实现:
static class MinStack2 {
record Data(int val, int min){
}
private final LinkedList<Data> stack = new LinkedList<>();
public void push(int val) {
if(stack.isEmpty()){ //第一次添加,新元素就是栈的最小值
stack.push(new Data(val, val));
}else{
stack.push(new Data(val, Math.min(val, stack.peek().min)));
}
}
public void pop() {
stack.pop();
}
public int top() {
return stack.peek().val;
}
public int getMin() {
return stack.peek().min;
}
}