题目
难度 简单
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
-
push(x)—— 将元素 x 推入栈中。 -
pop()—— 删除栈顶的元素。 -
top()—— 获取栈顶元素。 -
getMin()—— 检索栈中的最小元素。
示例:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
提示:
pop、top和getMin操作总是在 非空栈 上调用。
辅助栈
我们要维持正常栈的特性,比如说pop() top() push(x)。所以我们需要一个正常的栈来存储数据。同时我们需要一个方法来获取剩余元素中的最小值,这个也可以使用栈来实现。这个用来辅助记录的栈,我们称为 辅助栈
如上图,我们在每存储一个元素时,判断是否比当前栈顶元素大,如果大则再次存入之前的栈顶元素。这样生成的右边栈,就是与左边栈一一对应,当前栈的最小值。需要注意左边pop时右边也要pop,保持一直,这样右边栈顶元素一直是左边栈剩余元素的最小值。如下图:
代码实现
import java.util.Stack;
//leetcode submit region begin(Prohibit modification and deletion)
class MinStack {
Stack<Integer> normalStack;
Stack<Integer> minStack;
/**
* initialize your data structure here.
*/
public MinStack() {
normalStack = new Stack<>();
minStack = new Stack<>();
}
public void push(int x) {
normalStack.push(x);
if (minStack.isEmpty()) {
minStack.push(x);
} else {
if (x <= minStack.peek()) {
minStack.push(x);
} else {
//如果存入的值比当前栈顶大,那么再存入一个当前栈顶的元素
minStack.push(minStack.peek());
}
}
}
public void pop() {
normalStack.pop();
minStack.pop();
}
public int top() {
return normalStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
解法优化
上面说道的使用 辅助栈的解法,比较好理解,个人推荐。不过提交后,发现其实还有其他更优的解法。
如上图,自定义一个Node,里面除了存储Next,Value还记录当前的最小值。而且构建链表的时候注意是 反向链表。这样最后一个元素就存在head的位置。
我们top()和getMin()都是取head就行。
push(x)的时候存储value外,需要比较下x与之前head的min的哪个小的,存储小的。
class MinStack {
//自定义一个Node,里面除了存储Next,Value还记录当前的最小值
class Node {
private int min;
private int val;
private Node next;
private Node(int val, int min) {
this(val, min, null);
}
private Node(int val, int min, Node next) {
this.val = val;
this.min = min;
this.next = next;
}
}
Node head;
public MinStack() {
}
public void push(int x) {
if (head == null) {
head = new Node(x, x);
} else {
// push(x)的时候存储value外,需要比较下x与之前head的min的哪个小的,存储小的。
// 反向链表
head = new Node(x, Math.min(x, head.min), head);
}
}
public void pop() {
head = head.next;
}
public int top() {
return head.val;
}
public int getMin() {
return head.min;
}
}
运行结果:
相似题型:面试题 03.02. 栈的最小值