leetcode 155:最小栈

本文介绍了如何设计一个最小栈,支持push、pop、top和getMin操作,并能在常数时间内检索到最小元素。文章通过三种不同的思路展示了实现方法,包括暴力法、使用辅助栈和常数级额外空间的解决方案,最后给出了每种方法的Java代码实现及性能分析。
摘要由CSDN通过智能技术生成

leetcode 155:最小栈

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

  • push(x) —— 将元素 x 推入栈中。

  • pop() —— 删除栈顶的元素。

  • top() —— 获取栈顶元素。

  • getMin() —— 检索栈中的最小元素。

示例:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
​
输出:
[null,null,null,null,-3,null,0,-2]
​
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

提示:

  • poptopgetMin 操作总是在 非空栈 上调用。

Related Topics

设计

思路1:暴力法

class MinStack {
    int[] stack = new int[10000];
    int last = -1;
​
    public MinStack() {
​
    }
    
    public void push(int val) {
        stack[++last] = val;
    }
    //因为操作都是在非空栈进行
    public void pop() {
        last--;
    }
    
    public int top() {
        return stack[last];
    }
    
    public int getMin() {
        int min = stack[0];
        for(int i = 1 ; i <= last;i++){
            if(min >stack[i]){
                min = stack[i];
            }
        }
        return min;
    }
}
解答成功:
            执行耗时:53 ms,击败了7.10% 的Java用户
            内存消耗:42.8 MB,击败了11.99% 的Java用户

思路2:使用辅助栈存储当前值和之前的最小值

class MinStack {
    int[] stack = new int[10000];
    int last = -1;
​
    //存储栈中当前值之前的最小值
    int[] tempStack = new int[10000];
​
    public MinStack() {
​
    }
    //在入栈的时候给
    public void push(int val) {
        stack[++last] = val;
        tempStack[last] = val;
​
        if(last >0 && tempStack[last-1] < val){
            tempStack[last] = tempStack[last-1];
        }
​
​
    }
    //因为操作都是在非空栈进行
    public void pop() {
        last--;
    }
    
    public int top() {
        return stack[last];
    }
    
    public int getMin() {
​
        return tempStack[last];
    }
}
解答成功:
            执行耗时:4 ms,击败了98.32% 的Java用户
            内存消耗:44.8 MB,击败了5.01% 的Java用户

思路3:常数级的额外空间思路

  • 思路:栈中存储第i项值和前i-1项最小值的差值 dis = val - min

  • 那么怎么恢复这个val呢?

    • 如果 dis > 0,直接用栈中存储的值加上min

    • 如果dis <= 0 那么这个val在push的时候会被更新成min,说明min就是val。

  • 因为栈中存储的是差值,当min是-2147483648时,dis就会溢出,所以使用long型解决溢出问题。

class MinStack {
    long[] stack = new long[10000];
    int last = -1;
    long dis = 0;
    long min = 0;
    //存储栈中当前值之前的最小值
    //int[] tempStack = new int[10000];
​
    public MinStack() {
​
    }
​
    /**
     * 通过dis来判断
     * dis = val - min
     * 当dis大于0时,说明min不变还是最小值 出栈时 只需根据 dis + min 返回元素即可
     * dis 小于0时,最小值是val 需要更新min ,但是前一个值需要通过原来的最小值计算
     *              此时,最小值已经更新成val ,原来的最小值计算就是val - dis
     *              但是,val已经更新了min,所以原来的最小值通过min- dis
     * @param val
     */
    public void push(int val) {
​
        if(last == -1){
            stack[++last] = (long) 0;
            min = (long) val;
        }else{
            dis = (long) (val - min);
​
            stack[++last] = dis;
            //更新最小值
            if(val < min){
                min = (long) val;
            }
        }
​
    }
    //因为操作都是在非空栈进行
    public void pop() {
        dis = stack[last--];
​
        /**
         * 入栈时,通过val -min(这是前n-1项的最小值) 存储
         * 如果dis > 0 说明val大于前n-1项的最小值 最小值不需要更新
         *      return dis + min;
         * 如果 dis <= 0
         *      第n项的最小值此时就是val
         *      这个时候需要计算啊出前n-1项的最小值 然后更新
         *      前n-1的最小值 = val - dis = min - dis
         *      return min
         */
        //
        if(dis < 0){
            min = min - dis;
        }
​
    }
    
    public int top() {
        dis = stack[last];
        if(stack[last] > 0){
            return (int) (dis + min);
        }else{
            return (int) min;
        }
    }
    
    public int getMin() {
        return (int) min;
    }
}
解答成功:
            执行耗时:4 ms,击败了98.27% 的Java用户
            内存消耗:44.5 MB,击败了5.05% 的Java用户
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值