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

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12601046.html
Copyright © 2011-2022 走看看