zoukankan      html  css  js  c++  java
  • 构造一个可以在固定时间内返回最小元素值的栈

    我一开始没想太多,觉得把标准库里现有的数据结构拼一下,完全就可以了,这是我的代码:

    class MinStack {
    private:
        multiset<int> sortedElems;
        list<int>     stack;
    public:
        void push(int x) {
            sortedElems.insert(x);
            stack.push_back(x);
        }
        
        void pop() {
            if (stack.empty()){
                return;
            }
            sortedElems.erase(sortedElems.find(stack.back()));
            stack.pop_back();
        }
        
        int top() {
            return stack.back();
        }
        
        int getMin() {
            return *sortedElems.cbegin();
        }
    };

    这个思路有点偷懒,就是你既然要求返回最小元素所用的时间是固定的,那么原先理论上需要用来查找的开销我就挪到别的地方去,没错,我把它们分摊到了 pop() he push() 上。

    但毕竟我的这个算法很愚蠢,所以就算是返回最小值的时间变短了,但总时间还是很长,效率低下, 共用了 54ms。

    当我的方法不算是最快的那一种的时候,我就会看一下讨论区里其他朋友的方法,结果果然发现了更高效的方法,原代码是 Java 版本,我改写了自己的一份 C++ 版本:

    class MinStack {
    private:
        long long min = 0;
        stack<long long> _stack;
    public:
        void push(int x) {
            auto&& n = static_cast<long long>(x);
            if (_stack.empty()) {
                _stack.push(0L);
                min = n;
                return;
            }
            _stack.push(n - min);
            if (n < min){
                min = n;
            }
        }
        
        void pop() {
            if (_stack.empty()){
                return;
            }
            
            auto popedNum = _stack.top();
            if (popedNum < 0L){
                min -= popedNum;
            }
            
            _stack.pop();
        }
        
        int top() {
            auto topNum = _stack.top();
            if (topNum > 0) {
                return static_cast<int>(min + topNum);
            }
            return static_cast<int>(min);
        }
        
        int getMin() {
            return static_cast<int>(min);
        }
    };

    这个算法很有意思,是一种空间换时间的策略,我之前的想法中,最小值和栈中存储的值是割裂开的,存储是存储,然后再单独求出最小值。

    而这种方法就不同了,它是把最小值与每个值在 push() 时通过运算建立联系,并在 pop() 时通过逆运算求得原先的值,因此所用时间只有 28ms。

    对了,还有一个细节要注意,就是用于存储的值,选用的类型是 long long。因为其中用到了加法,int 之间的相加可能会溢出,所以采用 long long 来存储。

  • 相关阅读:
    2019-2020-1 20199327《Linux内核原理与分析》第九周作业
    交替重复 批处理
    2019-2020-1 20199327《Linux内核原理与分析》第八周作业
    内核模块编译
    2019-2020-1 20199327《Linux内核原理与分析》第七周作业
    2019-2020-1 20199327《Linux内核原理与分析》第六周作业
    MenuOS扩展
    2019-2020-1 20199327《Linux内核原理与分析》第五周作业
    2019-2020-1 20199327《Linux内核原理与分析》第四周作业
    2019-2020-1 20199327《Linux内核原理与分析》第三周作业
  • 原文地址:https://www.cnblogs.com/wuOverflow/p/4719820.html
Copyright © 2011-2022 走看看