Min Stack
package cn.edu.xidian.sselab.stack;
import java.util.Stack;
/**
*
* @author zhiyong wang
* title: Min Stack
* content:
* Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
*
* push(x) -- Push element x onto stack.
* pop() -- Removes the element on top of the stack.
* top() -- Get the top element.
* getMin() -- Retrieve the minimum element in the stack.
* 一开始没弄懂这个题的意思,现在搞懂了:最小栈相当于一个辅助栈,用来存储另一一个栈的最小元素的集合:
* 具体可以这样理解,因为push(x),pop(),top()都可以在O(1)时间内完成,但是getMin()获取最小值的这种操作就不能在O(1)时间内完成
* 所以这里借助了最小栈的概念
* (1)push的时候,stack肯定会存放数据,如果最小栈是空的或者最小栈的栈顶元素小于要存放数据元素,最小栈也会存放数据【这样最小栈一直维护着一个从栈顶到栈底是由小到大排序的】,否则最小栈不存放数据
* (2)pop的时候,如果stack是空的则不管,如果不是空的,则弹出栈顶元素,如果最小栈不是空的,并且栈顶元素与stack栈弹出的元素相等,那么最小栈也需要弹出栈顶元素
* (3)top的时候,观察stack是否为空,如果为空则不管,如果不为空,则查看栈顶元素,与最小栈没有关系
* (4)getMin的时候,这个时候跟stack是没有关系的,如果最小栈不为空,在查看栈顶元素
*
*
*/
public class MinStack {
Stack<Integer> stack = new Stack<Integer>();
Stack<Integer> minStack = new Stack<Integer>();
public void push(int x){
stack.push(x);
if(minStack.isEmpty() || minStack.peek() >= x)
minStack.push(x);
}
public void pop(){
if(stack.isEmpty())
return ;
int temp = stack.pop();
if(!minStack.isEmpty() && temp == minStack.peek())
minStack.pop();
}
public int top(){
return stack.peek();
}
public int getMin(){
return minStack.peek();
}
}
这个地方参考了讲解:http://www.tuicool.com/articles/zARfAj
这道题是关于栈的题目,实现一个栈的基本功能,外加一个获得最小元素的操作。正常情况下top,pop和push操作都是常量时间的,而主要问题就在于这 个getMin上面,如果遍历一遍去找最小值,那么getMin操作就是O(n)的,既然出出来了这道题就肯定不是这么简单的哈。比较容易想到就是要追溯 这个最小值,在push的时候维护最小值,但是如果pop出最小值的时候该如何处理呢,如何获得第二小的值呢?如果要去寻找又不是常量时间了。解决的方案 是再维护一个栈,我们称为最小栈,如果遇到更小的值则插入最小栈,否则就不需要插入最小栈(注意这里正常栈是怎么都要插进去的)。这里的正确性在于,如果 后来得到的值是大于当前最小栈顶的值的,那么接下来pop都会先出去,而最小栈顶的值会一直在,而当pop到最小栈顶的值时,一起出去后接下来第二小的就 在pop之后最小栈的顶端了。如此push时最多插入两个栈一个元素,是O(1),top是取正常栈顶,自然是O(1),而pop时也是最多抛出两个栈的 栈顶元素,O(1)。最后getMin只需要peek最小栈顶栈顶即可,所以仍是O(1),实现了所有操作的常量操作,空间复杂度是O(n),最小栈的大 小。代码如下