232. 用栈实现队列(Implement Queue using Stacks)E
英文题目
Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push, peek, pop, and empty).
Implement the MyQueue class:
void push(int x) Pushes element x to the back of the queue.
int pop() Removes the element from the front of the queue and returns it.
int peek() Returns the element at the front of the queue.
boolean empty() Returns true if the queue is empty, false otherwise.
Notes:
You must use only standard operations of a stack, which means only push to top, peek/pop from top, size, and is empty operations are valid.
Depending on your language, the stack may not be supported natively. You may simulate a stack using a list or deque (double-ended queue) as long as you use only a stack's standard operations.
Follow-up: Can you implement the queue such that each operation is amortized O(1) time complexity? In other words, performing n operations will take overall O(n) time even if one of those operations may take longer.
Example 1:
Input ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] Output [null, null, null, 1, 1, false] Explanation 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
Constraints:
1 <= x <= 9
At most 100 calls will be made to push, pop, peek, and empty.
All the calls to pop and peek are valid.
中文题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列的支持的所有操作(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) ,即使其中一个操作可能花费较长时间。
示例:
输入:
输入: ["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 操作)
双栈
将一个栈 inStack 当作输入栈,用于 push 传入的数据,另一个栈当作输出栈,用于 pop 和 peek 操作。
每次 pop 或 peek 时,若输出栈为空则将输入栈的全部数据依次弹出并压入输出栈
时间复杂度:push 和 empty 为O(1),pop 和 peek 为均摊 O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为O(1)
空间复杂度:O(n),n 是操作总数。对于有 n 次 push 操作的情况,队列中会有 n 个元素,故空间复杂度为 O(n)
# python3: 时间 44 ms, 击败 41.59%; 内存 15.85 MB, 击败 11.26% class MyQueue: def __init__(self): self.inStack = [] self.outStack = [] def push(self, x: int) -> None: self.inStack.append(x) def pop(self) -> int: if not self.outStack: while self.inStack: self.outStack.append(self.inStack.pop()) return self.outStack.pop() def peek(self) -> int: if not self.outStack: while self.inStack: self.outStack.append(self.inStack.pop()) return self.outStack[-1] def empty(self) -> bool: return not self.inStack and not self.outStack # Your MyQueue object will be instantiated and called as such: # obj = MyQueue() # obj.push(x) # param_2 = obj.pop() # param_3 = obj.peek() # param_4 = obj.empty()
// c++: 时间 0 ms, 击败 100%; 内存 6.75 MB, 击败 9.00% class MyQueue { private: stack<int> inStack; stack<int> outStack; public: MyQueue() {} void push(int x) { inStack.push(x); } int pop() { if (outStack.empty()) { while (!inStack.empty()) { outStack.push(inStack.top()); inStack.pop(); } } int res = outStack.top(); outStack.pop(); return res; } int peek() { if (outStack.empty()) { while (!inStack.empty()) { outStack.push(inStack.top()); inStack.pop(); } } return outStack.top(); } bool empty() { return inStack.empty() && outStack.empty(); } }; /** * Your MyQueue object will be instantiated and called as such: * MyQueue* obj = new MyQueue(); * obj->push(x); * int param_2 = obj->pop(); * int param_3 = obj->peek(); * bool param_4 = obj->empty(); */
// java: 时间 0 ms, 击败 100%; 内存 38.09 MB, 击败 97.80% class MyQueue { Deque<Integer> inStack; Deque<Integer> outStack; public MyQueue() { inStack = new LinkedList<>(); outStack = new LinkedList<>(); } public void push(int x) { inStack.push(x); } public int pop() { if (outStack.isEmpty()) { while (!inStack.isEmpty()) { outStack.push(inStack.peek()); inStack.pop(); } } int res = outStack.peek(); outStack.pop(); return res; } public int peek() { if (outStack.isEmpty()) { while (!inStack.isEmpty()) { outStack.push(inStack.peek()); inStack.pop(); } } return outStack.peek(); } public boolean empty() { return inStack.isEmpty() && outStack.isEmpty(); } } /** * Your MyQueue object will be instantiated and called as such: * MyQueue obj = new MyQueue(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.peek(); * boolean param_4 = obj.empty(); */
// go: 时间 0 ms, 击败 100%; 内存 1.81 MB, 击败 29.91% type MyQueue struct { inStack []int outStack []int } func Constructor() MyQueue { return MyQueue{} } func (this *MyQueue) Push(x int) { this.inStack = append(this.inStack, x) } func (this *MyQueue) Pop() int { if len(this.outStack) == 0 { for len(this.inStack) > 0 { this.outStack = append(this.outStack, this.inStack[len(this.inStack)-1]) this.inStack = this.inStack[:len(this.inStack)-1] } } res := this.outStack[len(this.outStack)-1] this.outStack = this.outStack[:len(this.outStack)-1] return res } func (this *MyQueue) Peek() int { if len(this.outStack) == 0 { for len(this.inStack) > 0 { this.outStack = append(this.outStack, this.inStack[len(this.inStack)-1]) this.inStack = this.inStack[:len(this.inStack)-1] } } return this.outStack[len(this.outStack)-1] } func (this *MyQueue) Empty() bool { return len(this.inStack) == 0 && len(this.outStack) == 0 } /** * Your MyQueue object will be instantiated and called as such: * obj := Constructor(); * obj.Push(x); * param_2 := obj.Pop(); * param_3 := obj.Peek(); * param_4 := obj.Empty(); */
// javascript: 时间 56 ms, 击败 84.77%; 内存 41.1 MB, 击败 15.13% var MyQueue = function() { this.inStack = []; this.outStack = []; }; /** * @param {number} x * @return {void} */ MyQueue.prototype.push = function(x) { this.inStack.push(x); }; /** * @return {number} */ MyQueue.prototype.pop = function() { if (!this.outStack.length) { while (this.inStack.length) { this.outStack.push(this.inStack.pop()); } } return this.outStack.pop(); }; /** * @return {number} */ MyQueue.prototype.peek = function() { if (!this.outStack.length) { while (this.inStack.length) { this.outStack.push(this.inStack.pop()); } } return this.outStack[this.outStack.length-1]; }; /** * @return {boolean} */ MyQueue.prototype.empty = function() { return !this.inStack.length && !this.outStack.length; }; /** * Your MyQueue object will be instantiated and called as such: * var obj = new MyQueue() * obj.push(x) * var param_2 = obj.pop() * var param_3 = obj.peek() * var param_4 = obj.empty() */