Browse curriculum

Implement Queue using Stacks

Build a first-in, first-out queue from two last-in, first-out stacks, moving values across only when the output stack runs empty.

Problem Understanding

Implement Queue using Stacks (LeetCode 232): build a queue class, MyQueue, with push(x) to add at the back, pop() to remove and return the front, peek() to return the front, and empty(). You may only use stack operations: push to top, peek or pop from top, size and is empty. LeetCode never calls pop or peek on an empty queue.

Example: push(1), push(2), peek(), pop(), empty() returns 1, 1, false.

The Intuition: Pour One Stack into the Other

A stack gives back the newest value; a queue must give back the oldest. Pouring a stack into a second stack reverses it, so the oldest value ends up on top.

  1. Pushes go to inStack.
  2. Reads come from outStack. If outStack is empty, first pour all of inStack into it.
  3. Never pour while outStack has values. Everything on outStack is older than anything in inStack, so its top is still the front.

That last rule is what makes it cheap: each value is poured exactly once. Compare Min Stack, which also pairs two stacks so that every operation stays O(1).

Interactive Walkthrough

EACH VALUE MOVES ONCE

EMPTY

operations

push 1
push 2
peek
pop
empty

inStack

empty

outStack

empty

Size

0

Moves

0

returned

Nothing read yet

 

Two empty stacks: inStack takes every push, outStack hands values back out in queue order

Next

push 1: put it on top of inStack

Ops

Legend & Complexity

The value just pushed, or just moved onto outStack

The front of the queue, read by peek

Each operation

O(1) amortized

Space

O(n)

Each move is its own step, so you can watch the order flip as values cross from inStack to outStack. Try Moves once: eight operations and only four moves, because value 4 waits in inStack until outStack runs dry.

Dry Run Table

Input: push 1, push 2, peek, pop, empty. Stacks are written bottom first.

Operation What happens inStack outStack Returns
push 1 onto inStack [1] []
push 2 onto inStack [1, 2] []
peek outStack is empty: move 2, then 1 [] [2, 1] 1
pop outStack is not empty: no move [] [2] 1
empty 2 is still in outStack [] [2] false

The Solution Template

Two stacks and a move helper that only runs when outStack is empty. The C version uses fixed arrays, since LeetCode makes at most 100 calls.

Implement Queue using Stacks Code
1class MyQueue {
2 constructor() {
3 this.inStack = [];
4 this.outStack = [];
5 }
6
7 push(x) {
8 this.inStack.push(x);
9 }
10
11 move() {
12 if (this.outStack.length === 0) {
13 while (this.inStack.length) {
14 this.outStack.push(this.inStack.pop());
15 }
16 }
17 }
18
19 pop() {
20 this.move();
21 return this.outStack.pop();
22 }
23
24 peek() {
25 this.move();
26 return this.outStack[this.outStack.length - 1];
27 }
28
29 empty() {
30 return this.inStack.length === 0 && this.outStack.length === 0;
31 }
32}

Edge Cases & Common Mistakes

  • Moving when outStack is not empty: values pushed later would land on top of older ones, and pop would return the wrong value.
  • empty checking one stack: values can sit in either stack, so check both.
  • Pushing straight onto outStack: a new value belongs at the back of the queue, which is inStack.
  • Moving values back after every pop: correct, but O(n) per operation instead of O(1) amortized.

Summary

Push onto inStack; pop and peek from outStack, pouring inStack across only when outStack is empty. Each value moves once, so every operation is O(1) amortized, with O(n) space.

More practice: DSA interview questions with answers · patterns cheat sheet

The approach, step by step

  1. Push

    Put every pushed value on top of inStack.

  2. Move when empty

    Before pop or peek, if outStack is empty, pop every value off inStack onto outStack.

  3. Read outStack

    pop and peek use outStack's top; empty is true only when both stacks are empty.

Frequently asked questions

Why does moving the values reverse them into queue order?

Popping inStack gives the newest value first. Pushing each one onto outStack in that order leaves the newest at the bottom and the oldest on top, which is the front of the queue.


Why is pop O(1) amortized and not O(n)?

A single pop can move n values, but each value is moved from inStack to outStack at most once in its life, because the move only happens when outStack is empty. Over any sequence of operations the total work is O(number of operations), so the average per operation is O(1).


Why not move values back to inStack after each pop?

That would make every pop O(n). Leaving values on outStack is safe because everything there is older than everything in inStack, so outStack's top is always the front of the queue until it runs out.


Can a queue be built with one stack?

Only by using the call stack as the second one: a recursive pop that unwinds to the bottom value. It is still two stacks in effect, and every pop costs O(n).

New to the technique behind this problem? Watch it run step by step:

Stack Visualization

Applying for software engineering roles? Free, no sign-up:

AI resume checker: match your resume to the job description