CMD Guide
HomeDSAQueues

easy Implement Stack using Queues

Problem Statement

Implement a stack using only two queues. The stack should behave like a typical last-in-first-out (LIFO) stack, meaning that the last element added should be the first one to be removed.

Implement a Solution class that supports the following operations:

Note: You can only use the basic operations of a queue, such as adding an element to the back, removing an element from the front, checking the size, and verifying if the queue is empty.

Input and Output Format

The input and output for this problem are structured using two separate arrays:

Examples

Example 1

Example 2

Example 3

Constraints:

Try it yourself

Try solving this question here:

🎯 STRICT STANDOUT — Implement Stack using Queues (problem)

1. Why / judgment

This problem forces you to pay for LIFO on top of FIFO. Either push is O(n) (rotate so newest sits at front) or pop is O(n) — you choose which op is hot.

2. Expected trace (K11/K13)

push 5, push 10, top→10, pop→10, empty→false
After two pushes with push-O(n) scheme: main queue front is 10, then 5.
Empty stack: empty() true; pop/top not called (constraints: valid).

3. Pattern cue (K12)

Name: Stack via queue rotation (two-queue or one-queue).

Recognition: “only queue ops” + LIFO API.

When-NOT: real systems use a true stack/deque; this is an interview constraint drill, not production design. When-NOT queue for DFS: if you already have a stack type, do not fake it with queues for performance.

4. Interviewer follow-ups

Q1. Make pop O(n) instead of push?
A: Yes — keep natural FIFO; on pop rotate n−1 to back, then remove front.

Q2. One queue enough?
A: Yes: on push, enqueue then rotate size−1 times.

✅ Solution Implement Stack using Queues

Problem Statement

Implement a stack using only two queues. The stack should behave like a typical last-in-first-out (LIFO) stack, meaning that the last element added should be the first one to be removed.

Implement a Solution class that supports the following operations:

  • Solution(): A constructor to initialize the object.
  • push(int x): Adds an element x to the top of the stack.
  • pop(): Removes the element from the top of the stack and returns it.
  • top(): Retrieves the element on the top of the stack without removing it.
  • empty(): Checks whether the stack is empty or not and returns true or false accordingly.

Note: You can only use the basic operations of a queue, such as adding an element to the back, removing an element from the front, checking the size, and verifying if the queue is empty.

Examples

Example 1

  • Input:

    • ["Solution", "push", "push", "top", "pop", "empty"]
    • [[], [5], [10], [], [], []]
  • Expected Output: [null, null, null, 10, 10, false]

  • Explanation:

    • push(5) adds 5 to the stack.
    • push(10) adds 10 to the top of the stack.
    • top() returns 10 since it's the top element.
    • pop() removes 10 and returns it.
    • empty() returns false because 5 is still in the stack.

Example 2

  • Input:
    • ["Solution", "push", "push", "push", "pop", "top", "pop", "empty"]
    • [[], [1], [2], [3], [], [], [], []]
  • Expected Output: [null, null, null, null, 3, 2, 2, false]
  • Explanation:
    • push(1) adds 1 to the stack.
    • push(2) adds 2 on top of 1.
    • push(3) adds 3 on top of 2.
    • pop() removes 3 and returns it.
    • top() returns 2, the new top element.
    • pop() removes 2 and returns it.
    • empty() returns false since 1 is still in the stack.

Example 3

  • Input:
    • ["Solution", "push", "top", "pop", "empty"]
    • [[], [99], [], [], []]
  • Expected Output: [null, null, 99, 99, true]
  • Explanation:
    • push(99) adds 99 to the stack.
    • top() returns 99.
    • pop() removes 99 and returns it.
    • empty() returns true because the stack is now empty.

Constraints:

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

Solution

To solve this problem using two queues, the key idea is to simulate the behavior of a stack by manipulating the elements in the queues. The main challenge is to ensure that the pop and top operations return the most recently added element. To achieve this, we maintain two queues:

  1. Main Queue: This holds the current state of the stack.
  2. Helper Queue: This is used temporarily during the push operation.

The approach involves always pushing the new element into the helper queue, then transferring all elements from the main queue to the helper queue. Finally, we swap the roles of the two queues. This way, the last added element always stays at the front of the main queue, ensuring the correct behavior for pop and top. This approach works well because it maintains the order of elements correctly, making it a valid stack implementation using queues.

Step-by-Step Algorithm

  1. Initialization:

    • Start by creating two empty queues named queue1 and queue2.
    • These queues will be used to simulate the behavior of a stack.
    • queue1 will hold the elements in stack order, while queue2 will be a helper queue used during the push operation.
  2. Push Operation (push(int x)):

    • Step 1: Add the element x to queue2.
      • This step places the new element at the front of the queue, which will eventually become the top of the stack.
    • Step 2: Transfer all elements from queue1 to queue2.
      • This step ensures that the newly added element x stays at the front of the queue, maintaining the LIFO order of the stack.
      • Each element is removed from queue1 and added to queue2.
    • Step 3: Swap the roles of queue1 and queue2.
      • After transferring all elements, queue2 now holds the elements in the correct stack order.
      • Swapping the queues ensures that queue1 will always be the queue representing the current state of the stack, while queue2 becomes the empty helper queue for the next operation.
  3. Pop Operation (pop()):

    • Step 1: Remove and return the front element from queue1.
      • Since queue1 holds the elements in the correct stack order, removing the front element effectively removes the top element of the stack.
  4. Top Operation (top()):

    • Step 1: Return the front element of queue1 without removing it.
      • This operation allows you to peek at the top element of the stack without modifying the stack itself.
  5. Empty Operation (empty()):

    • Step 1: Check if queue1 is empty.
      • If queue1 is empty, the stack is empty, so return true.
      • Otherwise, return false to indicate that the stack still contains elements.

Algorithm Walkthrough

Let's go through the algorithm step by step using the example:

Input:

  • ["Solution", "push", "push", "top", "pop", "empty"]
  • [[], [5], [10], [], [], []]

Steps:

  1. Operation: Solution (Constructor)

    • Step: Initialize two empty queues, queue1 and queue2.
    • Result: Both queues are empty, ready to simulate the stack operations.
  2. Operation: push(5)

    • Step 1: Add 5 to queue2.
      • queue2 now contains: [5]
    • Step 2: Transfer all elements from queue1 to queue2.
      • queue1 is empty, so no elements are transferred.
      • queue2 remains: [5]
    • Step 3: Swap the roles of queue1 and queue2.
      • After swapping, queue1 contains: [5]
      • queue2 is now empty: []
  3. Operation: push(10)

    • Step 1: Add 10 to queue2.
      • queue2 now contains: [10]
    • Step 2: Transfer all elements from queue1 to queue2.
      • Move 5 from queue1 to queue2.
      • queue2 now contains: [10, 5]
      • queue1 is now empty: []
    • Step 3: Swap the roles of queue1 and queue2.
      • After swapping, queue1 contains: [10, 5]
      • queue2 is now empty: []
  4. Operation: top()

    • Step 1: Return the front element of queue1 without removing it.
      • The front element of queue1 is 10, so 10 is returned as the top element of the stack.
    • Result: The returned value is 10.
  5. Operation: pop()

    • Step 1: Remove and return the front element from queue1.
      • The front element of queue1 is 10, so 10 is removed and returned.
      • queue1 now contains: [5]
    • Result: The returned value is 10.
  6. Operation: empty()

    • Step 1: Check if queue1 is empty.
      • queue1 contains one element (5), so the stack is not empty.
      • Return false.
    • Result: The returned value is false.

Final Output:

The operations return the following results in sequence: [null, null, null, 10, 10, false].

Code

java
import java.util.LinkedList;
import java.util.Queue;

class Solution {

  // Two queues to simulate stack behavior
  Queue<Integer> queue1;
  Queue<Integer> queue2;

  // Constructor to initialize the queues
  public Solution() {
    queue1 = new LinkedList<>();
    queue2 = new LinkedList<>();
  }

  // Push element x onto the stack
  public void push(int x) {
    // Add the element to queue2
    queue2.add(x);

    // Move all elements from queue1 to queue2 to maintain stack order
    while (!queue1.isEmpty()) {
      queue2.add(queue1.remove());
    }

    // Swap the names of queue1 and queue2
    Queue<Integer> temp = queue1;
    queue1 = queue2;
    queue2 = temp;
  }

  public int pop() {
    return queue1.remove(); // Remove and return the front of queue1, which is the stack's top
  }

  public int top() {
    return queue1.peek(); // Peek at the front of queue1, which is the stack's top
  }

  public boolean empty() {
    return queue1.isEmpty(); // Check if queue1 is empty
  }

  // Main method to test the stack implementation
  public static void main(String[] args) {
    Solution myStack = new Solution();
    myStack.push(5);
    myStack.push(10);
    System.out.println(myStack.pop()); // 10
    System.out.println(myStack.top()); // 5
    System.out.println(myStack.pop()); // 5
    System.out.println(myStack.empty());
  }
}

Complexity Analysis

Time Complexity

  1. push(int x):

    • The push operation adds an element to queue2 and then moves all elements from queue1 to queue2.
    • If there are n elements in the stack, this operation will take time to transfer all elements.
    • Thus, the time complexity of the push operation is .
  2. pop():

    • The pop operation removes the front element of queue1.
    • This operation takes constant time because it only involves removing the front element of the queue.
    • Thus, the time complexity of the pop operation is .
  3. top():

    • The top operation returns the front element of queue1 without removing it.
    • This operation also takes constant time .
    • Thus, the time complexity of the top operation is .
  4. empty():

    • The empty operation checks whether queue1 is empty, which is a constant-time operation.
    • Thus, the time complexity of the empty operation is .

Space Complexity

  • The space complexity of the implementation is where n is the number of elements in the stack. This is because two queues are used, each of which can hold up to n elements.

🎯 STRICT STANDOUT — Solution Implement Stack using Queues

1. Why / judgment

Push-heavy scheme: new element enters helper queue first, old main drains behind it, then swap — so main.front is always stack top. Pop/top/empty stay Θ(1).

2. Hand-run + complexity (K11/K13)

push(5): q2=[5]; drain q1; swap → q1=[5]
push(10): q2=[10]; drain 5 → q2=[10,5]; swap → q1=[10,5]
top → 10; pop → 10; q1=[5]; empty → false
push is Θ(n) transfers; pop/top/empty Θ(1). Space Θ(n) for elements (two queue objects, one empty).

One-queue variant push(x):
  q.add(x); for i in 1..size-1: q.add(q.remove())  // rotate
  also Θ(n) push, Θ(1) pop.

3. Pattern (K12)

Name: Make newest the front via rotation.

When-NOT: need true O(1) stack — use ArrayDeque/stack. Interview only. Do not confuse with “queue using stacks” (dual problem).

4. Interviewer follow-ups

Q1. Amortized O(1) all ops?
A: Not with only queues in worst-case multipop sequences without fancy accounting; standard solution has O(n) on one side.

Q2. Why swap references not copy?
A: O(1) role change after O(n) drain.

✅ Solution Generate Binary Numbers from 1 to N

Problem Statement

Given an integer N, generate all binary numbers from 1 to N and return them as a list of strings.

Examples

Example 1

  • Input: N = 2
  • Output: ["1", "10"]
  • Explanation: The binary representation of 1 is "1", and the binary representation of 2 is "10".

Example 2

  • Input: N = 3
  • Output: ["1", "10", "11"]
  • Explanation: The binary representation of 1 is "1", the binary representation of 2 is "10", and the binary representation of 3 is "11".

Example 3

  • Input: N = 5
  • Output: ["1", "10", "11", "100", "101"]
  • Explanation: These are the binary representations of the numbers from 1 to 5.

Solution

To solve this problem, we'll use a queue to systematically generate binary numbers. Initially, we enqueue the binary representation of '1'. For each number from 1 to N, we perform the following steps: dequeue the front element of the queue and record it as the current binary number. Then, we generate the next two binary numbers by appending '0' and '1' to the current number and enqueue these new numbers. This process continues until we have generated all binary numbers up to N. This method efficiently leverages the queue's FIFO (First In First Out) nature to build upon previous binary numbers, ensuring a systematic and orderly generation of binary representations.

Step-by-Step Algorithm

  1. Initialize a Queue: Create a queue data structure which will be used to hold binary numbers in string format.

  2. Start with '1': Enqueue the binary representation of the first number, which is '1'.

  3. Iterate up to N: Set up a loop that runs from 1 to N. This loop controls how many binary numbers you need to generate.

  4. Dequeue and Output: In each iteration of the loop, dequeue an element from the front of the queue. This element is the binary representation of the current number. Store or print this number as part of the solution.

  5. Generate Next Binary Numbers:

    • Take the dequeued binary number and append '0' to it, forming the next binary number. Enqueue this new number back into the queue.
    • Repeat the above step, but this time append '1' instead of '0'.
  6. Repeat the Process: Continue this process until the loop completes its iteration up to N. Each iteration generates the next set of binary numbers based on the current numbers in the queue.

Algorithm Walkthrough

mediaLink
mediaLink

Code

Here is how we can implement this algorithm:

java
import java.util.LinkedList;
import java.util.Queue;

public class Solution {

  public String[] generateBinaryNumbers(int n) {
    Queue<String> q = new LinkedList<String>();
    q.add("1"); // Initialize the queue with "1".

    String[] res = new String[n]; // Create an array to store the binary numbers.
    for (int i = 0; i < n; i++) {
      res[i] = q.poll(); // Dequeue the current binary number and add it to the result array.
      q.add(res[i] + "0"); // Enqueue the next binary number by appending "0".
      q.add(res[i] + "1"); // Enqueue the next binary number by appending "1".
    }

    return res; // Return the array containing binary numbers.
  }

  public static void main(String[] args) {
    Solution sol = new Solution();
    String[] binaryNums = sol.generateBinaryNumbers(5); // Generate binary numbers for testing.
    for (String binaryNum : binaryNums) {
      System.out.println(binaryNum); // Print each generated binary number.
    }
  }
}

Complexity Analysis

Time Complexity

  • Queue operations: The algorithm uses a queue to generate binary numbers in order. For each of the n numbers, it performs the following operations:
    • Dequeue operation: This is done once per number and takes time.
    • Enqueue two new numbers: For each number, two new binary numbers (appending '0' and '1') are generated and enqueued. Each enqueue operation also takes time.
  • Since there are n iterations, and each iteration involves constant-time operations for dequeueing and enqueueing, the overall time complexity is .

Overall time complexity: .

Space Complexity

  • Result array: The result array stores the n binary numbers, which takes space.

  • Queue space: The queue stores intermediate binary numbers. At any point in time, the queue holds at most two binary numbers for each element processed. This means that the maximum number of elements in the queue is proportional to n, so the queue requires space.

Overall space complexity: .

🎯 STRICT STANDOUT — Solution Generate Binary Numbers

1. Why / judgment

Queue BFS expands each prefix to prefix+0 and prefix+1. FIFO yields numeric order. Prefer this pattern when teaching BFS generation; in apps, Integer.toBinaryString is fine.

2. Hand-run + complexity (K11/K13)

N=5 seed "1"
pop 1 → enq 10,11
pop 10 → enq 100,101
pop 11 → enq 110,111
pop 100,101 → stop after 5
→ ["1","10","11","100","101"] ✓
N=0/negative: return empty (guard).
Time: Θ(N) queue ops + Θ(N log N) for string building (immutable).
Space: Θ(N) queue + Θ(N log N) output.
Page claim “O(n) overall” understates string work — state both.

3. Pattern (K12)

BFS generator over implicit tree. When-NOT stack: DFS order ≠ 1..N binary list order. When-NOT: single conversion of one integer.

4. Interviewer follow-ups

Q1. Why not enqueue only up to N without over-generating?
A: You can stop children when count hits N; still O(N) useful outputs.

Q2. LinkedList vs ArrayDeque?
A: ArrayDeque preferred; both correct FIFO.

🧩 Pattern · Queues

Recognize it: Process in arrival order / level-by-level → a FIFO queue (BFS).

▶ Visualize this problem (step it, predict each fork)
⛶ Open this problem debugger in explore mode
🤖 Don't fully get this? Learn it with Claude

Stuck on Implement Stack using Queues? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Implement Stack using Queues** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Implement Stack using Queues** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Implement Stack using Queues**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Implement Stack using Queues**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes