题目来源:https://leetcode-cn.com/problems/implement-queue-using-stacks/
题目描述
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
进阶:
你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。
题目大意
- 使用两个栈模拟队列的基本操作,并且需要尽可能使得操作均摊时间复杂度为O(1),
- 可以先使一个栈中的元素顺序和个数表示当前队列中元素的顺序和个数,然后当获取队列的队首元素时,将所有栈中的元素出栈并且用另一个栈装着每次出栈的元素,则就可以使此时另一个栈进行取top首部元素时就是队列的元素顺序
栈模拟队列
class MyQueue {
public:
stack<int> front;
stack<int> back;
MyQueue() {
}
void push(int x) {
front.push(x);
}
int pop() {
int ans = peek();
back.pop();
return ans;
}
int peek() {
// 需要时我再进行栈中元素的移动
if(!back.empty()) return back.top();
else{
while(!front.empty()){
back.push(front.top());
front.pop();
}
}
return back.top();
}
bool empty() {
// 此处少进行多次判断,可降低ms
return (front.empty() && back.empty());
}
};
复杂度分析
- 时间复杂度:O(1)。当执行pop或peek操作时,如果栈(back)为空,对front中的所有元素进行搬迁,否则是O(1)时间复杂度,可知当n次pop或top中,有1次O(n)搬迁操作,其余n-1次O(1)为O(1)时间复杂度,所以平摊下来时间复杂度为O(1)
- 空间复杂度:O(n)。维护两个栈,单个栈中元素个数最大与push的数据量等长