zoukankan      html  css  js  c++  java
  • 《面试题 03.05. 栈排序》——惰性更新

    栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作:push、pop、peek 和 isEmpty。当栈为空时,peek 返回 -1。

    示例1

     输入:
    ["SortedStack", "push", "push", "peek", "pop", "peek"]
    [[], [1], [2], [], [], []]
     输出:
    [null,null,null,1,null,2]

    示例2

     输入: 
    ["SortedStack", "pop", "pop", "push", "pop", "isEmpty"]
    [[], [], [], [1], [], []]
     输出:
    [null,null,null,null,null,true]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/sort-of-stacks-lcci

    这个题目最容易想到的办法是我们使用一个辅助栈,当push的val比当前栈顶元素大时,就先将当前栈中比val大的元素push到辅助栈中,然后当前栈压入val,再将辅助栈中的元素重新压回当前栈,这样就保证了栈顶元素一定是最小的。具体c++代码实现如下:

     1 class SortedStack {
     2     stack<int> st;
     3 public:
     4     SortedStack() {
     5     }
     6 
     7     void push(int val) {
     8         if(st.empty()||val<=st.top())
     9         {
    10             st.push(val);
    11         }
    12         else
    13         {
    14             stack<int> tmp;
    15             while(!st.empty()&&st.top()<val)
    16             {
    17                 tmp.push(st.top());
    18                 st.pop();
    19             }
    20             st.push(val);
    21             while(!tmp.empty())
    22             {
    23                 st.push(tmp.top());
    24                 tmp.pop();
    25             }
    26         }
    27     }
    28     
    29     void pop() {
    30         if(st.empty()){cout<<"empty";return;}
    31         st.pop();
    32     }
    33     
    34     int peek() {
    35         if(st.empty()){return -1;}
    36         return st.top();
    37     }
    38     
    39     bool isEmpty() {
    40         return st.empty();
    41     }
    42 };
    43 
    44 /**
    45  * Your SortedStack object will be instantiated and called as such:
    46  * SortedStack* obj = new SortedStack();
    47  * obj->push(val);
    48  * obj->pop();
    49  * int param_3 = obj->peek();
    50  * bool param_4 = obj->isEmpty();
    51  */

      我们压入一个长度为n的升序序列,那么第i次push操作,我们将进行i次pop()和i次push()操作,总的操作次数将高达n^2次,效率实在是不高。仔细一想,如果出现连续的push()工作,而每一次我们都从当前栈倒出一部分,装入val,再将辅助栈中的元素倒回,我们不妨假设:

    *某一次push的val_1,它应处于位置 x (1<=x<=n+1,当前已有n个元素), 我们需要进行的push、pop操作是(n+1-x)*2+1,

    *接着,下一次的val_2,它应处于位置y(1<=y<=n+2,当前已有n+1个元素),我们需要进行的push、pop操作是(n+1-y)*2+1;

      值得思考的是,这两次操作中我们是否做了多余的工作?答案是肯定的。试想一下,若我们在找到val_1的位置后,暂时保留辅助栈中的元素,下一次的val_2,如果val_2>val_1,意味着我们只需要把辅助栈中比val_2大的几个元素push进原始栈,然后就可以得到val_2的位置,这其中的操作量大大减少了。两个栈不再是你满我空,你空我满的状态,而是达到了一种微妙的平衡,这个平衡就是,原始栈中的元素>=val>辅助栈中的元素。辅助栈自底向上逐渐增大,原始栈自顶向下逐渐增大。这样,当需要最小元素时,在辅助栈底或原始栈顶取得。

    class SortedStack {
        stack<int> sortStack;
        stack<int> helpStack;
    public:
        SortedStack() {
        }
        void push(int val) {
            int Max = sortStack.empty() ? INT_MAX : sortStack.top();
            int Min = helpStack.empty() ? INT_MIN : helpStack.top();
            while(true)
            {
                if(val > Max)
                {
                    helpStack.push(sortStack.top());
                    sortStack.pop();
                    Max = sortStack.empty() ? INT_MAX : sortStack.top();
                }
                else if(val < Min)
                {
                    sortStack.push(helpStack.top());
                    helpStack.pop();
                    Min = helpStack.empty() ? INT_MIN : helpStack.top();
                }
                else
                {
                    sortStack.push(val);
                    break;
                }//此时已经满足(elems in sortStack)>= val >(elems in helpstack);
            }
        }
        
        void pop() {
            while(!helpStack.empty())
            {
                sortStack.push(helpStack.top());
                helpStack.pop();
            }                                          //辅助栈中的元素压回原始栈中
            if(!sortStack.empty())
                sortStack.pop();
        }
        
        int peek() {
            while(!helpStack.empty())
            {
                sortStack.push(helpStack.top());
                helpStack.pop();
            }                                       //辅助栈中的元素压回原始栈中
    
            return sortStack.empty() ? -1 : sortStack.top();
        }
        
        bool isEmpty() {
            return sortStack.empty()&&helpStack.empty();
        }
    };

    就很nice

  • 相关阅读:
    Android面试题目整理与解说(二)
    大学?做码农?做project师?
    图形学领域的关键算法及源代码链接
    假设在本地搭一个server和mysql数据库环境,假设使用java来訪问数据库
    [容斥原理] hdu 4135 Co-prime
    leetcode第一刷_Merge Intervals
    关于HashMap的一些深入探索与理解
    摄像头拍照上传
    rowid快速分页解析
    flare-spork: 自己维护的Pig on Spark项目
  • 原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12601046.html
Copyright © 2011-2022 走看看