3.(155)最小栈

2020年3月21日

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.

Example:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) -- 将元素 x 推入栈中。
  • pop() -- 删除栈顶的元素。
  • top() -- 获取栈顶元素。
  • getMin() -- 检索栈中的最小元素。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

方法1

最直接的方法是用两个栈,一个保存正常的入栈出栈的值,另一个栈去存最小值,也就是用当前栈顶保存当前所有元素的最小值,流程如下:

  1. 将第一个元素入栈
  2. 新加入的元素如果大于栈顶元素,那么新加入的元素就不处理
  3. 新加入元素如果小于等于栈顶元素,那么新元素入栈
  4. 出栈元素不等于栈顶元素,不操作
  5. 出栈元素等于栈顶元素,将栈顶元素出栈
class MinStack{
    private Stack<Integer> stack;
    private Stack<Integer> minStack;
    
    public MinStack(){
        stack=new Stack<>();
        minStack=new Stack<>();
    }
    
    public void push(int x){
        stack.push(x);
        if(!minStack.isEmpty()){
            int top=minStack.peek();
            //小于等于的时候才入栈
            if(x<=top){
            	minStack.push(x);
            }
        }else{
            minStack.push(x);
        }
    }
    
    public void pop(){
        int pop=stack.pop();
        
        int top=minStack.peek();
        //等于的时候再出栈
        if(pop==top){
            minStack.pop();
        }
    }
    
    public int top(){
        return stack.peek();
    }
    
    public int getMin(){
        return minStack.peek();
    }
    
    public int getMin(){
        return minStack.peek();
    }
}

方法2

方法1中使用了两个栈实现,那么现在尝试用一个栈实现,只用一个变量去保存最小值,如果新压入的值更小,那么在压入新元素前将原来的min压入栈中,并更新最小值

class minStack{
    int min = Integer.MIN_VALUE;
    Stack<Integer> stack = new Stack<Integer>();
    public void push(int x){
        if(x<=min){
            stack.push(min);
            min=x;
        }
        stack.push(x);
    }
    
    public void pop(){
        if(stack.pop()==min){
            min = stack.pop();
        }
    }
    
    public int top(){
        return stack.peek();
    }
    
    public int getMin(){
        return min;
    }
}

方法3

从方法2中可以看出,关键要解决的问题是当有新的更小值的时候,之前的最小值怎么办?

方法3用另一种思路,通过min存储当前最小值,栈中存储入栈的值与最小值的差值

public class MinStack{
    long min;
    Stack<long> stack;
    
    public MinStack(){
        stack=new Stack<>();
    }
    
    public void push(int x){
        if(stack.isEmpty()){
            min=x;
            stack.push(x-min);
        }else{
            stack.push(x-min);
            if(x<min){
                min=x;
            }
        }
    }
    
    public void pop(){
        if(stack.isEmpty()) return;
        long pop = stack.pop();
        if(pop<0){
            min=min-pop;
        }
    }
    
    public int top(){
        long top=stack.peek();
        if(top<0){
            return (int)(min);
        }else{
            return (int)(top+min);
        }
    }
    
    
    public int getMin(){
        return (int) min;
    }
}

上述解法的一个缺点是保存的是差值,所以可能造成溢出,所以用了范围更大的long类型,这个解法在最小值更新时不需要把之前的最小值存起来,会节省一些空间

方法4

不用java提供的stack,在Node结点中增加min字段

class MinStack{
    class Node{
        int value;
        int min;
        Node next;
        
        Node(int x,int min){
            this.value=x;
            this.min=min;
            next=null;
        }
    }
    Node head;
    
    public void push(int x){
        if(null==head){
            head=new Node(x,x);
        }else{
            Node n = new Node(x,Math.min(x,head.min))
            n.next=head;
            head=n;
        }
    }
    
    public void pop(){
        if(head!=null)
            head=head.next;
    }
    
    public int top(){
        if(head!=null)
            return head.value;
        return -1;
    }
    
    public int getMin(){
        if(head!=null)
            return head.min;
        return -1;
    }
}
posted @ 2020-03-21 20:41  小苏呀  阅读(125)  评论(0编辑  收藏  举报