Description
232. Implement Queue using Stacks
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 elementxto 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()Returnstrueif the queue is empty,falseotherwise.
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, andempty. - All calls to
popandpeekare valid.
Follow-up: Can you implement the queue such that each operation is amortized time complexity?
Approach 1: Two Stacks (Push , Pop )
Intuition
To make pop and peek operations , we keep the front of the queue always at the top of the primary stack s1.
When pushing x:
- Move all elements from
s1tos2. - Push
xintos1. - Move all elements back from
s2tos1.
import java.util.Stack;
class MyQueue {
private Stack<Integer> s1;
private Stack<Integer> s2;
public MyQueue() {
s1 = new Stack<>();
s2 = new Stack<>();
}
public void push(int x) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
s1.push(x);
while (!s2.isEmpty()) {
s1.push(s2.pop());
}
}
public int pop() {
return s1.pop();
}
public int peek() {
return s1.peek();
}
public boolean empty() {
return s1.isEmpty();
}
}
Complexity
- Time Complexity:
push: — Moves all elements back and forth twice.pop,peek,empty: — Direct operations on top ofs1.
- Space Complexity: — Stores all elements across two stacks.
Most Optimized Solution: Two Stacks (Amortized )
Intuition
Instead of moving elements back and forth on every single push, use two distinct stacks:
inStack: Used solely for receiving newly pushed elements (push).outStack: Used solely for popping/peeking elements (pop/peek).
When pop() or peek() is called:
- If
outStackis empty, move all elements frominStackintooutStack. This reverses their order, making the oldest element sit at the top ofoutStack. - If
outStackis not empty, directly read or pop fromoutStack.
import java.util.Stack;
class MyQueue {
private Stack<Integer> inStack;
private Stack<Integer> outStack;
public MyQueue() {
inStack = new Stack<>();
outStack = new Stack<>();
}
public void push(int x) {
inStack.push(x);
}
public int pop() {
peek(); // Ensure outStack has elements
return outStack.pop();
}
public int peek() {
if (outStack.isEmpty()) {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
return outStack.peek();
}
public boolean empty() {
return inStack.isEmpty() && outStack.isEmpty();
}
}
Complexity
- Time Complexity:
push: — Always pushes directly intoinStack.pop,peek: Amortized — Each element is pushed toinStackonce and popped tooutStackonce across its entire lifetime.empty: — Checks if both stacks are empty.
- Space Complexity: — Stores elements distributed between
inStackandoutStack.
Easy Memory Rule
“Push into
inStack. Pop fromoutStack. IfoutStackis empty, dumpinStackintooutStackto reverse order.”