剑指Offer 30、包含min函数的栈

103 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

题目:要求自定义栈的数据结构,并且在该类型中实现一个可得到栈的最小元素的函数,所有函数的调用时间复杂度都要求为O(1)O(1)。本题和主站的155题对应。

解题思路

本题的关键是最小值,我们需要保证的是在push元素的时候就可以判断最小值为多少,并且在弹出元素之后也需要保证最小值是多少,如果最小值是当前弹出元素,则最小值需要被更新。简单的思路是使用一个变量来接收最小值,但当弹出栈元素后并不会更新最小值,此处给出两个思路来完成最小值的更新,解决的核心就是在push元素的时候同时保存最小值信息,那么我们可以:

  • 除了数据栈,还保存一个最小值栈,每次push元素的时候都检查元素的大小,并且将元素和最小值同时更新进入两个栈,出栈同理。
  • 可以只使用一个栈,这样这个栈中的数据结构为一个个数组,数组中只包含两个元素,其中第一个代表数据,第二个为当前的最小值。

根据这两个思路得到的代码分别为:

/**
	两个栈的方式
*/

class MinStack {

    Stack<Integer> min;
    Stack<Integer> stack;

    /** initialize your data structure here. */
    public MinStack() {
        min = new Stack();
        stack = new Stack();
    }
    
    public void push(int x) {
        if(!min.isEmpty()){
            int curMin = min.peek();
            if(x<curMin) curMin = x;
            min.push(curMin);
        }else{
            min.push(x);
        }
        stack.push(x);
    }
    
    public void pop() {
        if(!stack.isEmpty()){
            stack.pop();
            min.pop();
        }
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int min() {
        return min.peek();
    }
}

空间复杂度为O(N)O(N)。下面是使用数组的方式:

class MinStack {

    Stack<int[]> stack;

    /** initialize your data structure here. */
    public MinStack() {
        stack = new Stack();
    }
    
    public void push(int x) {
        if(!stack.isEmpty()){
            int curMin = stack.peek()[1];
            if(x<curMin) curMin = x;
            stack.push(new int[]{x, curMin});
        }else{
            stack.push(new int[]{x, x});
        }
    }
    
    public void pop() {
        stack.pop();
    }
    
    public int top() {
        return stack.peek()[0];
    }
    
    public int min() {
        return stack.peek()[1];
    }
}

时间和空间复杂度不变,但代码更加简洁。