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]
说明:
- 栈中的元素数目在[0, 5000]范围内。
解题思路
-
单栈排序
灵感来源于 O(1)空间复杂度反转栈 这道题。
题目没说让我们一次返回排好序的栈,只是要我们提供 push/pop/peek 这些栈的普通接口,所以我们可以把排序的工作降为获取栈内最小元素。
这样思路就很简单了,递归拿出元素进行比较就可以 —— 不用临时数组存元素,就用函数调用栈空间存元素嘛!
时间复杂度上,push 是 O(1) 但是 pop 和 peak 都是 O(n)。 -
双栈排序
题目说可以用一个临时栈,那我们就可以把上面的递归改成循环,把函数调用栈上的数据存入普通栈。
实际上,这才是大多数人的做法。
这种做法,维护了一个有序的栈,排序发生在 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