设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) —— 将元素 x 推入栈中。
- pop() —— 删除栈顶的元素。
- top() —— 获取栈顶元素。
- getMin() —— 检索栈中的最小元素。
给出两种解决方案:
1、辅助栈
思路是使用辅助栈来保存当前节点到之前节点的最小值。代码如下:
class MinStack {
// 数据栈
Deque<Integer> xStack;
// 辅助栈
Deque<Integer> minStack;
// 初始化方法
public MinStack() {
xStack = new LinkedList<>();
minStack = new LinkedList<>();
minStack.push(Integer.MAX_VALUE);
}
// 入栈
public void push (int x) {
xStack.push(x);
minStack.push(Math.min(minStack.peek(), x));
}
// 出栈
public void pop() {
xStack.poll();
minStack.poll();
}
// 获取栈顶元素
public int top() {
return xStack.peek();
}
// 获取最小值
public int getMin() {
return minStack.peek();
}
}
第二种解法,不使用额外的空间,栈中保存差值。
思路是栈中保存入栈值和最小值的差值。
入栈的时候,计算入栈值和最小值的差值,将其入栈,如果小于0,那么更新最小值。
出栈的时候,如果出栈值小于0,代表这里最小值发生改变,当时入栈的是当前的最小值,出栈值是当前的最小值减去之前的最小值,所以用当前的最小值减去这个差值,就是之前的最小值。
可以理解为,把栈分割成n段,每段他们的最小值是相同的,栈里保存的是入栈的值和当前最小值的差,而段与段的间隔,就是当前最小值入栈的时候,和前一段最小值的差。
这里需要注意一点,就是,不能再使用Integer来记录入栈的数据,因为它有可能超出整型的范围。
代码如下:
class MinStack {
// 差值栈
Deque<Long> xStack;
// 当前最小值
Integer minValue;
public MinStack() {
xStack = new LinkedList<>();
minValue = Integer.MAX_VALUE;
}
public void push(int x) {
// 差值栈空了 当前没有数据进来
if (xStack.isEmpty()) {
xStack.push(0L);
minValue = x;
} else {
xStack.push((long)x - minValue);
minValue = Math.min(minValue, x);
}
}
public void pop() {
long diff = xStack.pop();
if (diff < 0) {
// 这里pop出minValue
minValue = (int)(minValue - diff);
} else {
// 这里pop出minValue+diff
}
}
public int top() {
long diff = xStack.peek();
if (diff < 0) {
return minValue;
} else {
return (int)(minValue+diff);
}
}
public int getMin() {
return minValue;
}
}