题目: 155.最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
示例:
思路:
要能在常数时间内就能取到最小元素,考虑用一个额外的栈来存放最小值。主要考虑 push 操作和 pop 操作。
思路一:
每压入一个元素,最小栈也要压入一个元素 。
第一个元素压入普通栈的同时,也压入最小值栈;之后每压入一个元素都要进行判断:
如果该元素大于最小栈栈顶元素,则在最小栈中压入一个和最下栈栈顶元素相同的值 ;
如果该元素小于最小栈栈顶元素,则在最小栈中也压入这个元素 ;
如果该元素等于最小栈栈顶元素,则压入该元素和最小栈栈顶元素均可;
总结一下:当元素小于等于最小栈栈顶元素时,压入该元素;当元素大于最小栈栈顶元素时,压入和最小栈栈顶元素相同的值。写代码时,可以定义一个最小值变量min,根据情况改变min的值即可。
pop时,两个栈同时 pop 即可 。
代码:
public class MinStack {
private Deque<Integer> stack = new LinkedList<>(); //存放元素的栈
private Deque<Integer> minStack = new LinkedList<>(); //存放最小值的栈
public MinStack() {
}
public void push(int val) {
stack.push(val);
//同时也压入 minStack
int min = val;
if (!minStack.isEmpty() && val > minStack.peek()) {
min = minStack.peek();
}
minStack.push(min);
}
public void pop() {
stack.pop();
minStack.pop();
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
思路二:
思路二跟思路一差不多,区别在于最小值栈存储元素的条件以及pop操作。
当压入一个元素时,当这个元素小于等于最小值栈栈顶元素时才压入最小值栈(等于最小栈栈顶元素时为了处理重复的元素压栈),即当要压入栈的元素大于最小栈栈顶元素时,只压入存放元素的栈。特别情况为当第一个元素入栈时,也直接压入最小栈。
pop 操作时,需要进行判断:如果要 pop 的值不等于最小值栈栈顶元素,则只 pop 存放元素栈的栈顶元素;否则两个栈都要 pop (因为两个栈都压入该元素了)。
代码:
class MinStack {
Deque<Integer> stack = new LinkedList<>();
Deque<Integer> minStack = new LinkedList<>();
public MinStack() {
}
public void push(int val) {
stack.push(val);
if (minStack.isEmpty()) {
minStack.push(val);
} else {
if (val <= minStack.peek()) {
minStack.push(val);
}
}
}
public void pop() {
if (stack.isEmpty()) {
return;
}
int val = stack.peek();
if (val == minStack.peek()) {
minStack.pop();
}
stack.pop();
}
public int top() {
if (stack.isEmpty()) {
return -1;
}
return stack.peek();
}
public int getMin() {
if (minStack.isEmpty()) {
return -1;
}
return minStack.peek();
}
}