栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作: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