1-1 带有getmin功能的栈

题目描述

  • 实现一个特殊的栈,在实现栈基本功能的基础上,再实现返回栈中最小元素的操作。
  • 要求push,pop,getmin的操作时间复杂度都是 1。
  • 设计的栈类型可以使用现成的栈结构。

解题尝试

  • 自己最初的设想是在栈中增加一个成员变量min,用来记录最小值,每入栈一个元素就把这个元素和min比较,如果小于min就更新min的值。
  • 但是如果值为min的那个最小元素出栈了,那么就无法判断当前栈中哪个元素最小,所以不可行。

解题方法1

  • 除了实现基本功能的栈stack1之外,我们再定义一个栈stack2,用它来记录每一步的最小值。
  • 当stack1入栈了一个元素x,我们比较x与stack2的栈顶元素top的大小,如果x<=top,将x入栈到stack2,否则不进行处理。
  • 当stack1出栈一个元素(栈顶)x,我们比较x与stack2的栈顶元素top的大小,如果x==top,将stack2也出栈,否则不进行处理。
  • 这样stack2的栈顶始终保存着stack1的最小值,实现getmin方法只需要返回stack2栈顶即可。
    在这里插入图片描述
  • 实现代码
class stack{
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;
    stack(){
        this.stack1 = new Stack<>();
        this.stack2 = new Stack<>();
    }
    public void push(int x){
        this.stack1.push(x);
        if(this.stack2.empty() || x<=this.stack2.peek()){
           this.stack2.push(x);
        }
    }
    public Integer pop(){
        if(this.stack1.empty()){
            throw new RuntimeException("stack empty");
        }
       int e = this.stack1.pop();
       if(e == this.stack2.peek()){
           this.stack2.pop();
       }
       return e;
    }
    public Integer getmin(){
        if(this.stack2.empty()){
            throw new RuntimeException("stack empty");
        }
        return this.stack2.peek();
    }
}

解题方法2

  • 可以发现解题方法1中栈stack2中的元素数量少于stack1中元素数量,这样每次出栈的时候都要将stack1的栈顶与stack2的栈顶比较一下。
  • 我们也可以这样实现,在stack1入栈的时候,如果入栈元素x大于stack2的栈顶,就将stack2的栈顶再次入栈到stack2。这样可以使得stack2的元素数量与stack1是同步的,出栈的时候直接两个栈都进行出栈就好了。
    在这里插入图片描述
  • 代码如下:
class stack{
    private Stack<Integer> stack1;
    private Stack<Integer> stack2;
    stack(){
        this.stack1 = new Stack<>();
        this.stack2 = new Stack<>();
    }
    public void push(int x){
        this.stack1.push(x);
        if(this.stack2.empty() || x<=this.stack2.peek()){
           this.stack2.push(x);
        }
        if(x>this.stack2.peek()){
            this.stack2.push(this.stack2.peek());
        }
    }
    public Integer pop(){
        if(this.stack1.empty()){
            throw new RuntimeException("stack empty");
        }
        int e = this.stack1.pop();
        this.stack2.pop();
       return e;
    }
    public Integer getmin(){
        if(this.stack2.empty()){
            throw new RuntimeException("stack empty");
        }
        return this.stack2.peek();
    }
}
  • 两个方法的基本思路是一样的,都是使用stack2记录stack1每一步的最小值,两个方法的时间复杂度都为1,空间复杂度都为n。
  • 唯一的区别是,方法1中stack2入栈时稍省空间,出栈时稍费时间。方法2中stack2入栈时稍费空间,入栈时稍省时间。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章