2023.10.31
本题关键在于要求在能在常数时间内检索出最小元素。 其他四个方法都可以用普通的栈进行实现,最后一个方法“获取堆栈中最小元素” 可以借助一个新栈,专门用于存储栈中最小值的。具体细节看java代码:
class MinStack {
private Deque<Integer> stack;
private Deque<Integer> minStack;
public MinStack() {
stack = new LinkedList<>();
minStack = new LinkedList<>();
minStack.addFirst(Integer.MAX_VALUE);
}
public void push(int val) {
stack.addFirst(val);
minStack.addFirst(Math.min(minStack.getFirst(),val));
}
public void pop() {
stack.removeFirst();
minStack.removeFirst();
}
public int top() {
return stack.getFirst();
}
public int getMin() {
return minStack.getFirst();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
借助本题顺便复习了一下java中的栈。
在Java中,一般使用Deque而不使用Stack,因为Stack是实现的Vector接口,而Vector接口是Java中写的不太好的一个接口,为了保证线程安全,很多方法都用了synchronized修饰导致效率较低。相比较之下,像ArrayDeque,LinkedList这些线程不安全的,只需要在需要线程安全的时候用Collections.synchronizedCollection()转化成线程安全的就行了,效率会高一些。
其次,Stack只能上进上出,只能用于模拟栈,而Deque能上进上出,下进下出,既可以模拟栈又可以模拟队列,所以使用较为方便。
Deque的两个实现类:
- ArrayDeque:是数组结构,插入元素不能为null,无法确定数据量时,后期扩容会影响效率
- LinkList:链表结构,插入元素可以为null,无法确定数据量时,表现较好
Deque中常用方法:
-
addFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则引发异常。
-
addLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则引发异常。
-
offerFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则返回false。
-
offerLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则返回false。
-
getFirst() - 返回双端队列的第一个元素。如果双端队列为空,则引发异常。
-
getLast() - 返回双端队列的最后一个元素。如果双端队列为空,则引发异常。
-
peekFirst() - 返回双端队列的第一个元素。如果双端队列为空,则返回null。
-
peekLast() - 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
-
removeFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则引发异常。
-
removeLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则引发异常。
-
pollFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则返回null。
-
pollLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则返回null。
方法主要就是在头部尾部:增、删、查。 一共6种,每种又根据返回值的不同又分两种,总共12个方法。