zoukankan      html  css  js  c++  java
  • 每日一道 LeetCode (35):最小栈

    每天 3 分钟,走上算法的逆袭之路。

    前文合集

    每日一道 LeetCode 前文合集

    代码仓库

    GitHub: https://github.com/meteor1993/LeetCode

    Gitee: https://gitee.com/inwsy/LeetCode

    题目:最小栈

    题目来源:https://leetcode-cn.com/problems/min-stack/

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

    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.
    ``` 
    
    提示:
    
    - pop、top 和 getMin 操作总是在 非空栈 上调用。
    
    ## 解题思路
    
    看到这道题的第一个反应,这不就是一个数据结构栈么, Java 直接提供了啊,这还用做么?
    
    当我把题仔细的又读了一遍以后发现,这里面有一个 `getMin()` 检索栈中的最小元素是 JDK 所没有提供的,那么这道题实际上就是在问,如何在栈的数据结构中检索栈中最小的元素。
    
    经过一番仔细的思索,嗯,确认是我不会的那道题。
    
    这就很尴尬了,打开答案看答案吧。
    
    答案上的结果是加一个辅助栈来进行记录,记录添加到栈里最小的元素。。。
    
    好吧,我服了,这方案确实可以。
    
    往下翻了翻,结果还有人玩的更花,还把这个方案拆分成两种方案:同步法和不同步法。
    
    直接一个大写的 NB 。
    
    ## 方案一:同步法
    
    所谓的同步法就是在向数据栈中添加元素的时候,一起向辅助栈中也添加元素,数据栈出栈的时候辅助栈也一起出栈,辅助栈最后添加进来的数字保持最小,只有当将要进栈的数字比栈顶的数字小才能进栈,否则就将和栈顶的数字一样的数字重新进一次栈。
    
    ```java
    public class MinStack {
    
        private Stack<Integer> data;
        private Stack<Integer> helper;
    
        /** initialize your data structure here. */
        public MinStack() {
            data = new Stack<> ();
            helper = new Stack<> ();
        }
    
        public void push(int x) {
            data.push(x);
            // 只有小于栈顶的数字才能进栈,否则重新将栈顶的数字进栈
            if (helper.isEmpty() || helper.peek() >= x) {
                helper.push(x);
            } else {
                helper.push(helper.peek());
            }
    
        }
    
        public void pop() {
            if (!data.isEmpty()) {
                data.pop();
                helper.pop();
            }
    
        }
    
        public int top() {
            if (!data.isEmpty()) {
                return data.peek();
            }
            throw new RuntimeException("栈中元素为空,非法操作");
        }
    
        public int getMin() {
            if(!helper.isEmpty()){
                return helper.peek();
            }
            throw new RuntimeException("栈中元素为空,此操作非法");
        }
    }
    

    方案二:不同步法

    上面的同步法是只数据栈和辅助栈进栈出栈都是同步操作的,那么在外面的辅助栈中,能不能只存最小的值,因为它本身设计的使命就是用来查询最小值的。

    public class MinStack1 {
    
        private Stack<Integer> data;
        private Stack<Integer> helper;
    
        /** initialize your data structure here. */
        public MinStack1() {
            data = new Stack<> ();
            helper = new Stack<> ();
        }
    
        public void push(int x) {
            data.push(x);
            // 辅助栈只会进栈小值
            if (helper.isEmpty() || helper.peek() >= x) {
                helper.push(x);
            }
        }
    
        public void pop() {
            if (!data.isEmpty()) {
                int top = data.pop();
                // 只有当出栈的值也是小值的时候辅助栈也出栈
                if(top == helper.peek()){
                    helper.pop();
                }
            }
        }
    
        public int top() {
            if (!data.isEmpty()) {
                return data.peek();
            }
            throw new RuntimeException("栈中元素为空,非法操作");
        }
    
        public int getMin() {
            if(!helper.isEmpty()){
                return helper.peek();
            }
            throw new RuntimeException("栈中元素为空,此操作非法");
        }
    }
    

    耗时和前面的方法是一样的,只是我们所使用的辅助栈的空间变小了,但是在出栈的时候需要经过判断才能出栈。

    扫描二维码关注「极客挖掘机」公众号!
    作者:极客挖掘机
    定期发表作者的思考:技术、产品、运营、自我提升等。

    本文版权归作者极客挖掘机和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    如果您觉得作者的文章对您有帮助,就来作者个人小站逛逛吧:极客挖掘机
  • 相关阅读:
    C#基于LibUsbDotNet实现USB通信(一)
    Visual Studio 删除空行
    不安全代码只会在使用 /unsafe 编译的情况下出现
    VS2013 中 CString类型转换为LPCSTR类型
    Linux 下各文件夹的含义
    每日算法---Two Sum
    跟我一步一步写出MongoDB Web 可视化工具(二)
    跟我一步一步写出MongoDB Web 可视化工具(一)
    springcloud 微服务之间传递token解决方案
    Git设定不合并的文件
  • 原文地址:https://www.cnblogs.com/babycomeon/p/13607311.html
Copyright © 2011-2022 走看看