https://leetcode.com/problems/implement-queue-using-stacks/
Use the stack to implement the following operations of the queue:
push(x)-puts an element at the end of the queue.
pop()-removes an element from the queue header.
peek()--Returns the element at the head of the queue.
Empty()-returns whether the queue is empty.
example:
MyQueue queue = new MyQueue();
queue. push(1);
queue. push(2);
queue. peek(); // Return 1
queue. pop(); // Return 1
queue. Empty(); // Return false
description:
You can only use standard stack operations-that is, only push to top, peek/pop from top, size, and is empty operations are legal.
The language you are using may not support stacks. You can use list or deque (double-ended queue) to simulate a stack, as long as it is a standard stack operation.
Assume that all operations are valid, (for example, an empty queue will not call pop or peek operations).
-Stack -Queue
The topic requires the use of the stack's native operations to implement the queue, which means pop and push need to be used. But we know that pop and push are both operations at the top of the stack, while the enque and deque of the queue are operations at both ends of the queue. At first glance, it seems that a stack cannot be completed.
Let's analyze the process.
If you push four numbers into the stack separately 1, 2, 3, 4
, Then the situation of the stack at this time should be:
If you pop or peek according to the requirements of the topic at this time, it should return 1, and 1 is at the bottom of the stack. We cannot operate directly. If we want to return 1, we must first get 2, 3, and 4 out of the stack separately.
However, if we do this, although 1 will return normally, won't 2, 3, and 4 disappear forever? One short answer method is to save 2, 3, and 4 **. And the title said that only the data structure of the stack can be used, so we consider using an additional stack to store the pop-up 2, 3, and 4.
(Pop it out and don't throw it away, but save it)
The whole process is similar to this:
For example, at this time, we want to push a 5, then it's probably like this:
However, this process can also occur in the push stage.
In short, we need to flip the array between the two stacks once during push or pop.
-Use auxiliary stack (dual stack) when pushing
-Language support: JS, Python, Java
Javascript Code:
/*
* @lc app=leetcode id=232 lang=javascript
*
* [232] Implement Queue using Stacks
*/
/**
* Initialize your data structure here.
*/
var MyQueue = function () {
// tag: queue stack array
this.stack = [];
this.helperStack = [];
};
/**
* Push element x to the back of queue.
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function (x) {
let cur = null;
while ((cur = this.stack.pop())) {
this.helperStack.push(cur);
}
this.helperStack.push(x);
while ((cur = this.helperStack.pop())) {
this.stack.push(cur);
}
};
/**
* Removes the element from in front of queue and returns that element.
* @return {number}
*/
MyQueue.prototype.pop = function () {
return this.stack.pop();
};
/**
* Get the front element.
* @return {number}
*/
MyQueue.prototype.peek = function () {
return this.stack[this.stack.length - 1];
};
/**
* Returns whether the queue is empty.
* @return {boolean}
*/
MyQueue.prototype.empty = function () {
return this.stack.length === 0;
};
/**
* 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()
*/
Python Code:
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
self. stack = []
self. help_stack = []
def push(self, x: int) -> None:
"""
Push element x to the back of queue.
"""
while self. stack:
self. help_stack. append(self. stack. pop())
self. help_stack. append(x)
while self. help_stack:
self. stack. append(self. help_stack. pop())
def pop(self) -> int:
"""
Removes the element from in front of queue and returns that element.
"""
return self. stack. pop()
def peek(self) -> int:
"""
Get the front element.
"""
return self. stack[-1]
def empty(self) -> bool:
"""
Returns whether the queue is empty.
"""
return not bool(self. stack)
# 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()
Java Code
class MyQueue {
Stack<Integer> pushStack = new Stack<> ();
Stack<Integer> popStack = new Stack<> ();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
while (! popStack. isEmpty()) {
pushStack. push(popStack. pop());
}
pushStack. push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while (! pushStack. isEmpty()) {
popStack. push(pushStack. pop());
}
return popStack. pop();
}
/** Get the front element. */
public int peek() {
while (! pushStack. isEmpty()) {
popStack. push(pushStack. pop());
}
return popStack. peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return pushStack. isEmpty() && popStack. 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();
*/
Complexity analysis
-Time complexity: O(N)
, where N is the number of elements in the stack, because we have to reverse it every time.
-Spatial complexity: O(N)
, where N is the number of elements in the stack, one more auxiliary stack is used, and the size of this auxiliary stack is the same as the size of the original stack.
-A queue implementation stack is useful for similar topics. The idea is exactly the same. If you are interested, you can try it. -Stack shuffling is also done with the help of another stack. From this point of view, there are similarities between the two.
In fact, there are cases where two stacks are used to implement queues in reality, so why should we use two stacks to implement a queue?
In fact, the implementation of using two stacks instead of one queue is to separate read and write operations to the same queue in multiple processes. One stack is used for reading and the other is used for writing. Conflicts will occur between read and write operations if and only if the read stack is full or the write stack is empty.
When only one thread reads and writes to the stack, there is always one stack that is empty. In a multithreaded application, if we only have one queue, for thread safety, we need to lock the entire queue when reading or writing to the queue. In the implementation of the two stacks, as long as the write stack is not empty, the lock of the push
operation will not affect the pop
.
For more questions, please visit my LeetCode questions warehouse:https://github.com/azl397985856/leetcode . It is currently 40K stars.
You can also follow my official account "Force Buckle Plus" to get more fresher LeetCode questions.