Description

225. Implement Stack using Queues

Implement a last-in-first-out (LIFO) stack using only standard operations of a queue (push to back, peek/pop from front, size, and is empty).

Implement the MyStack class:

  • void push(int x) Pushes element x to the top of the stack.
  • int pop() Removes the element on the top of the stack and returns it.
  • int top() Returns the element on the top of the stack.
  • boolean empty() Returns true if the stack is empty, false otherwise.

Example 1:

Input:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]

Output:
[null, null, null, 2, 2, false]

Explanation:

MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top();   // return 2
myStack.pop();   // return 2
myStack.empty(); // return False
 

Constraints:

  • 1 <= x <= 9
  • At most 100 calls will be made to push, pop, top, and empty.
  • All calls to pop and top are valid.

Follow-up: Can you implement the stack using only one queue?


Approach 1: Two Queues (Push , Pop )

Intuition

A queue is FIFO (First-In-First-Out), while a stack is LIFO (Last-In-First-Out). To make pop operations , we ensure the most recently pushed element is always at the front of q1.

When pushing x:

  1. Push x into an empty helper queue q2.
  2. Move all elements from q1 to q2.
  3. Swap q1 and q2.
import java.util.LinkedList;
import java.util.Queue;
 
class MyStack {
    private Queue<Integer> q1;
    private Queue<Integer> q2;
 
    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();
    }
    
    public void push(int x) {
        q2.add(x);
        while (!q1.isEmpty()) {
            q2.add(q1.poll());
        }
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;
    }
    
    public int pop() {
        return q1.poll();
    }
    
    public int top() {
        return q1.peek();
    }
    
    public boolean empty() {
        return q1.isEmpty();
    }
}
 

Complexity

  • Time Complexity:
    • push: — Moves all elements between queues.
    • pop, top, empty: — Direct operations on the front of q1.
  • Space Complexity: — Stores elements across two queues.

Most Optimized Solution: Single Queue (Follow-Up)

Intuition

Instead of using two queues, we can rotate a single queue internally upon each push.

When a new element x is added:

  1. Append x to the back of the queue.
  2. Remove elements from the front one by one and re-add them to the back (size - 1 times).
  3. This rotates the queue so x ends up at the very front.
import java.util.LinkedList;
import java.util.Queue;
 
class MyStack {
    private Queue<Integer> q;
 
    public MyStack() {
        q = new LinkedList<>();
    }
    
    public void push(int x) {
        q.add(x);
        int size = q.size();
        // Rotate all previous elements behind the newly added element
        for (int i = 0; i < size - 1; i++) {
            q.add(q.poll());
        }
    }
    
    public int pop() {
        return q.poll();
    }
    
    public int top() {
        return q.peek();
    }
    
    public boolean empty() {
        return q.isEmpty();
    }
}
 

Complexity

  • Time Complexity:
    • push: — Rotates existing elements to the back.
    • pop, top, empty: — Standard front-of-queue operations.
  • Space Complexity: — Uses only a single queue.

Easy Memory Rule

“Add new element to back, then rotate size - 1 items behind it so the newest element is at the front.”