设计一个有getMin功能的栈

本题来自程序员代码面试指南

  • 设计一个有getMin功能的栈
    实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
  • 要求
  1. pop、push、getMin操作的时间复杂度都是O (1)。
  2. 设计的栈类型可以使用现成的栈结构。
  • 解决方法
    俩个栈,一个是普通栈里面放数据,另一个栈里面放栈中最小值
  • 第一种方法在压栈时判断插入时为空栈或者元素小于等于当前栈顶元素,压入最小值栈中。
    如果弹栈元素大小等于(不可能小于)最小值栈顶元素,同时从最小值栈中弹出。
  • 第二种方法插入的元素比当前栈中最小值大,将最小值重复入栈。
    弹栈时同时弹出数据栈和最小值栈中的一个元素。

第二种方法和第一种的区别就是第一种数据栈和最小值栈里的数据量是不相等的,在弹栈时要判断弹出的元素是否和最小值栈栈顶元素相等,第二种方法只要弹栈就同时从最小值栈里弹出一个

public class Mystack1 implements Mystack{
    private Stack stackData;//存储数据的栈与正常栈功能相同
    private Stack stackMin;//保存每一步的最小值

    public Mystack1() {
        this.stackData = new Stack<>();
        this.stackMin = new Stack<>();
    }

    /**
     * 压栈操作
     *
     * @param newNum
     */
    public void push(int newNum) {
        if (this.stackMin.isEmpty()) {
            //最小值的栈是空的直接压入
            this.stackMin.push(newNum);
        } else if (newNum <= stackMin.peek()) {
            //插入元素小于等于当前栈顶元素,也压入栈中
            this.stackMin.push(newNum);
        }
        //数据压入数据栈
        this.stackData.push(newNum);
    }

    /**
     * 弹栈操作
     *
     * @return
     * @throws Exception
     */
    public int pop() throws Exception {
        //栈空报错
        if (this.stackData.isEmpty()) {
            throw new Exception("栈空,无数据返回");
        }
        int pop = this.stackData.pop();
        //如果弹栈元素大小等于最小值栈顶元素,同时从最小值栈中弹出
        if (pop == this.stackMin.peek()) {
            this.stackMin.pop();
        }
        return pop;
    }

    /**
     * 返回栈中最小的元素的值
     *
     * @return
     * @throws Exception
     */
    public int getMin() throws Exception {
        if (this.stackMin.isEmpty()) {
            //最小值栈空报错
            throw new Exception("栈空");
        }
        return this.stackMin.peek();
    }
}
public class Mystack2 implements Mystack{
    private Stack stackData;//存储数据的栈与正常栈功能相同
    private Stack stackMin;//保存每一步的最小值

    public Mystack2() {
        this.stackData = new Stack<>();
        this.stackMin = new Stack<>();
    }

    /**
     * 压栈操作
     *
     * @param newNum
     */
    public void push(int newNum) {
        if (this.stackMin.isEmpty()) {
            //最小值的栈是空的直接压入
            this.stackMin.push(newNum);
        } else if (newNum <= stackMin.peek()) {
            //插入元素小于等于当前栈顶元素,也压入栈中
            this.stackMin.push(newNum);
        } else {
            //插入的元素比当前栈中最小值大,将最小值重复入栈
            this.stackMin.push(this.stackMin.peek());
        }
        //数据压入数据栈
        this.stackData.push(newNum);
    }

    /**
     * 弹栈操作
     *
     * @return
     * @throws Exception
     */
    public int pop() throws Exception {
        //栈空报错
        if (this.stackData.isEmpty()) {
            throw new Exception("栈空,无数据返回");
        }
        //同时弹出数据栈和最小值栈中的一个元素
        int pop = this.stackData.pop();
        this.stackMin.pop();
        return pop;
    }

    /**
     * 返回栈中最小的元素的值
     *
     * @return
     * @throws Exception
     */
    public int getMin() throws Exception {
        if (this.stackMin.isEmpty()) {
            //最小值栈空报错
            throw new Exception("栈空");
        }
        return this.stackMin.peek();
    }
}
设计一个有getMin功能的栈_第1张图片
性能测试

循环一千万次发现第二种方法的运算时间上要少于第一种算法,这大概就是空间换时间吧
最后附上github地址

你可能感兴趣的:(设计一个有getMin功能的栈)