【栈】栈排序

LeetCode 面试题 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]

说明:

  1. 栈中的元素数目在[0, 5000]范围内。

解题思路

  1. 单栈排序
    灵感来源于 O(1)空间复杂度反转栈 这道题。
    题目没说让我们一次返回排好序的栈,只是要我们提供 push/pop/peek 这些栈的普通接口,所以我们可以把排序的工作降为获取栈内最小元素。
    这样思路就很简单了,递归拿出元素进行比较就可以 —— 不用临时数组存元素,就用函数调用栈空间存元素嘛!
    时间复杂度上,push 是 O(1) 但是 pop 和 peak 都是 O(n)。

  2. 双栈排序
    题目说可以用一个临时栈,那我们就可以把上面的递归改成循环,把函数调用栈上的数据存入普通栈。
    实际上,这才是大多数人的做法。
    这种做法,维护了一个有序的栈,排序发生在 push 阶段,peak 和 pop 都是 O(1) 操作,只有 push 是 O(n)。

参考代码

1. 单栈排序

// 最小元素在栈顶的栈
class SortedStack {
    stack<int> stk;
    int pickMin() {
        int val = stk.top();
        stk.pop();
        if (stk.empty()) return val;
        int val2 = pickMin();
        if (val <= val2) {
            stk.push(val2);
            return val;
        } else {
            stk.push(val);
            return val2;
        }
    }
public:
    SortedStack() {

    }
    
    void push(int val) {
        stk.push(val);
    }
    
    void pop() { // 空的时候也可能调用pop
        if (!isEmpty()) pickMin();
    }
    
    int peek() {
        if (isEmpty()) return -1;
        int val =  pickMin();
        stk.push(val);
        return val;
    }
    
    bool isEmpty() {
        return stk.empty();
    }
};

/**
 * Your SortedStack object will be instantiated and called as such:
 * SortedStack* obj = new SortedStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->isEmpty();
 */

2. 双栈排序

这里insert操作的时候要特别注意 stk 为空的情况。下面的两种写法,第二种写法更好,把判空始终放在while条件,从而把第一次插入元素和插入最大元素的两种情况统一了起来。

// 最小元素在栈顶的栈
class SortedStack {
    stack<int> stk;
    stack<int> tmp;
/*
    void InsertSortedStack(int val) {
        if (stk.empty()) {
            stk.push(val);
            return;
        }
        int top = stk.top();
        while (val > top) {
            tmp.push(top);
            stk.pop();
            if (stk.empty()) break;
            top = stk.top();
        }
        stk.push(val);
        while (!tmp.empty()) {
            top = tmp.top();
            tmp.pop();
            stk.push(top);
        }
    } // AC
*/
    void InsertSortedStack(int val) {
        while (!stk.empty()) {
            int top = stk.top();
            if (val <= top) break;
            tmp.push(top);
            stk.pop();
        }
        stk.push(val);
        while (!tmp.empty()) {
            int top = tmp.top();
            tmp.pop();
            stk.push(top);
        }
    } // AC
public:
    SortedStack() {

    }
    
    void push(int val) {
        InsertSortedStack(val);
    }
    
    void pop() {
        if (!isEmpty()) stk.pop();
    }
    
    int peek() {
        if (isEmpty()) return -1;
        return stk.top();
    }
    
    bool isEmpty() {
        return stk.empty();
    }
}; // AC
posted @ 2021-09-25 10:40  与MPI做斗争  阅读(107)  评论(0编辑  收藏  举报