Skip to content
dsa450for five year olds

Stacks & Queues · 27 of 38

Reverse a Queue using recursion

Turn a waiting line around using only "leave from the front" and "join at the back", with each helper holding one person until the rest are turned around.

Simple way
time O(n)
room O(n)
Clever way
time O(n)
room O(n)

The problem, simply

You get a queue, a waiting line. You may only take the front item out, add an item at the back, look at the front, and check if the line is empty. Reverse the line, so the back becomes the front. Use recursion: a function that calls itself.

A story to remember it

Picture it

queuebefore
outin12345frontback
queueafter
outin54321frontback

A queue lets you take from the front and add at the back. We want the same numbers in the opposite order.

  • looking now

Examples

Five numbers

In
[1, 2, 3, 4, 5]
Out
[5, 4, 3, 2, 1]

The front 1 ends at the back, and the back 5 ends at the front.

Two numbers

In
[10, 20]
Out
[20, 10]

10 waits while 20 is handled, then joins behind it.

Repeats

In
[3, 3, 1]
Out
[1, 3, 3]

Equal values do not matter. Each item is moved once.

One item or none

In
[7] and []
Out
[7] and []

A line of one, or an empty line, is already reversed.

Way 1: the simple way

Use a stack, a pile where the last one on comes off first. Pour the whole line onto the pile, then pour the pile back into the line.

  1. While the queue is not empty, take the front and push it on the stack.
  2. While the stack is not empty, pop the top and add it at the back of the queue.
stackhelper stack
12345top
queuequeue
outinempty

Way 1 halfway: all five numbers moved from the queue onto a stack. 5 is on top, so it will go back into the queue first.

  • looking now
java
import java.util.*;

class Solution {
    public void reverse(Queue<Integer> q) {
        Deque<Integer> stack = new ArrayDeque<>();
        while (!q.isEmpty()) stack.push(q.poll());     // the front goes to the bottom of the pile
        while (!stack.isEmpty()) q.offer(stack.pop()); // the last one in comes out first
    }
}

How long it takes: every item moves twice, O(n). Extra room: the stack holds all n items, O(n).

Way 2: the clever way

Do the same thing without writing a stack. Every function call that is still waiting sits on the call stack, so the computer keeps the pile for you.

  1. If the queue is empty, stop. That is the base case.
  2. Take the front item and hold it in a local variable.
  3. Call reverse on the rest of the queue.
  4. When that call returns, the rest is reversed. Add the held item at the back.

Each call holds one number and adds it back on the way out

01 / 12

stackcall stack
empty
queuequeue (front ... back)
outin12345frontback

Start with 1, 2, 3, 4, 5. Call reverse() on the whole queue.

  • looking now
  • done
  • answer
  • just added
java
import java.util.*;

class Solution {
    public void reverse(Queue<Integer> q) {
        if (q.isEmpty()) return;     // an empty line is already reversed
        int front = q.poll();        // hold the front item
        reverse(q);                  // a helper reverses the rest
        q.offer(front);              // the held item joins at the back
    }
}

How long it takes: one call per item and O(1) work in each, O(n). Extra room: n calls wait on the call stack at the deepest point, O(n). It is the same cost as Way 1; the pile just moved from your code into the call stack.

Watch out for

  • Adding the held item back before the recursive call. Then the queue never gets shorter, the calls never reach the base case, and the program overflows the call stack.
  • Forgetting the base case. The function would call poll() on an empty queue, get null, and crash when unboxing to int.
  • Making a new queue instead of changing the given one. The task is to reverse the queue in place.

What interviewers ask next

  • Reverse only the first k items. Recurse k times instead of until empty, then move the other n - k items from the front to the back.
  • Reverse a stack using recursion. Harder, because a stack only opens at the top. You need a second helper that inserts an item at the bottom, and it costs O(n^2).
  • Can you reverse a queue in place with O(1) extra room and only queue moves? No. A queue only rotates, and rotating never changes the circular order of the items, so something must hold items aside.
  • Reverse a linked list with recursion. The same "fix the rest, then fix me" idea, with arrows instead of a line.

Remember this

Grown-up words: the waiting line is a queue, the kids who stepped out are frames on the call stack, the empty line is the base case, and the helper doing the rest is the recursive call.