Leetcode(232)——用栈实现队列
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(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(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入:
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
提示:
- 1 <= x <= 9
- 最多调用 100 次
push、pop、peek和empty - 假设所有操作都是有效的 (例如,一个空的队列不会调用
pop或者peek操作)
进阶:
- 你能否实现每个操作均摊时间复杂度为 O(1)O(1)O(1) 的队列?换句话说,执行 nnn 个操作的总时间复杂度为 O(n)O(n)O(n) ,即使其中一个操作可能花费较长时间。
题解
方法:
思路
1. 由于题目要求我们使用双栈来表示一个队列,所以我们可以将一个栈当作输入栈,用于压入 push\texttt{push}push 传入的数据;另一个栈当作输出栈,用于 pop\texttt{pop}pop 和 peek\texttt{peek}peek 操作。
2. 每次 pop\texttt{pop}pop 或 peek\texttt{peek}peek 时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈,这样输出栈内元素的出栈顺序就是队列元素出队时先入先出(FIFO)的顺序。
代码实现
class MyQueue {
private:
stack<int> Q1; // Q1 用于 push,Q2 用于实现 pop 和 peek。
stack<int> Q2; // 实际上是将 Q1 的数据存入 Q2 从而实现翻转
public:
MyQueue():Q1(),Q2(){
}
void push(int x) {
Q1.push(x);
}
int pop() {
if(empty())
return -1;
else if(Q2.empty()){
while(Q1.empty()==false){
Q2.push(Q1.top());
Q1.pop();
}
}
int top = Q2.top();
Q2.pop();
return top;
}
//可以看出 pop 和 peek 的操作大部分是一样的
int peek() {
if(empty())
return -1;
else if(Q2.empty()){
while(Q1.empty()==false){
Q2.push(Q1.top());
Q1.pop();
}
}
return Q2.top();
}
bool empty() {
if(Q2.empty() && Q1.empty())
return true;
else return false;
}
};
复杂度分析
时间复杂度:push\texttt{push}push 和 empty\texttt{empty}empty 为 O(1)O(1)O(1),pop\texttt{pop}pop 和 peek\texttt{peek}peek 为均摊 O(1)O(1)O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为 O(1)O(1)O(1)
空间复杂度:O(n)O(n)O(n) ,其中 nnn 是操作总数。对于有 nnn 次 push\texttt{push}push 操作的情况,队列中会有 nnn 个元素,故空间复杂度为 O(n)O(n)O(n)。
本篇博客详细解析了如何使用两个栈来实现一个符合队列特性的数据结构,包括push、pop、peek和empty操作。在push时将元素压入输入栈,而在pop和peek时,如果输出栈为空,则将输入栈所有元素转移至输出栈,以保持队列的FIFO特性。代码实现中,push和empty操作的时间复杂度为O(1),而pop和peek操作在最坏情况下为O(n),但平均时间复杂度为O(1)。
386

被折叠的 条评论
为什么被折叠?



