Skip to main content
Queue Design

Queue Using Stacks

Use two stacks: push to stack1 (inbox). When you need to dequeue, if stack2 (outbox) is empty, pour everything from stack1 into stack2 (reversing the order). Then pop from stack2. Amortized O(1) per operation.

O(1) amortized
·
O(n)

How It Works

Two LIFO stacks compose into one FIFO queue because two reversals restore original order. Pushes go onto an inbox stack. To dequeue or peek, pop from an outbox stack; if the outbox is empty, first pour the entire inbox into it, which reverses the elements so the oldest sits on top. Crucially, transfer only when the outbox runs dry — the outbox already holds older elements in correct order, and pouring early would interleave them wrongly.

A single dequeue can cost O(n) during a transfer, but each element is moved exactly once in its lifetime: pushed to the inbox, poured once, popped from the outbox. Total work over any n operations is O(n), so every operation is amortized O(1).

Step-by-Step Visualization

Queue using two stacks
Input
1
2
3
Stack
1
2
3
Inbox[1, 2, 3]
Outbox[]
1/3

Code

Java
class QueueUsingStacks {
  Stack<Integer> inbox = new Stack<>();
  Stack<Integer> outbox = new Stack<>();

  void push(int x) { inbox.push(x); }

  int pop() {
    if (outbox.isEmpty())
      while (!inbox.isEmpty()) outbox.push(inbox.pop());
    return outbox.pop();
  }

  int peek() {
    if (outbox.isEmpty())
      while (!inbox.isEmpty()) outbox.push(inbox.pop());
    return outbox.peek();
  }
}

Tips & Gotchas

1Two stacks: inbox and outbox
2Push to inbox. When popping, if outbox empty, pour inbox into outbox
3Amortized O(1) because each element is moved at most once

Practice Problems

  • 1Implement Queue using Stacks
  • 2Implement Stack using Queues
  • 3Design Circular Queue

About the Queue Design Pattern

Classic design problems that test your understanding of how queues work internally.

Key insight

BFS = queue. If you need shortest path in an unweighted graph or level-order traversal, reach for a queue. Monotonic deques solve sliding window extremes in O(n).

Common Queue / Deque Interview Problems

  • Binary Tree Level Order Traversal
  • Sliding Window Maximum
  • Rotting Oranges
  • Shortest Path in Binary Matrix
  • Implement Queue using Stacks

Frequently Asked Questions

Why is amortized O(1) an acceptable answer when one call can take O(n)?

Amortized analysis bounds the average over any operation sequence, and here each element pays for its own single transfer. Unless the problem demands strict worst-case latency — as some real-time systems do — the amortized bound is the standard and expected answer.

What is the classic mistake in this design?

Pouring the inbox into the outbox on every dequeue, or whenever the inbox is non-empty. That both breaks FIFO order when the outbox still holds older elements and destroys the amortized bound by moving elements repeatedly. Transfer only when the outbox is empty.

How does the reverse problem, a stack from queues, differ?

It is inherently costlier with plain FIFO queues: one operation (push or pop) must rotate up to n−1 elements to expose the newest, giving O(n) for that operation. The two-stack queue is the direction where amortized O(1) is achievable.