We need to build a queue (FIFO: first in, first out) using only stacks (LIFO: last in, first out). These two data structures have opposite ordering. When you push elements 1, 2, 3 onto a stack, popping gives you 3, 2, 1. A queue should give you 1, 2, 3 in the same order they went in.
The question is how to reverse the order of elements using stacks. Pushing elements onto one stack and then popping them all into a second stack reverses the order. The element that was at the bottom of the first stack ends up on top of the second stack, which is the element that should come out first in a queue.
What separates the approaches is efficiency, specifically which operation pays the cost of moving elements between stacks. There are two main strategies, and they make opposite choices.
1 <= x <= 9 → Values stay small, so there are no overflow concerns and a plain int is enough in every language.100 calls → The volume is low enough that any correct approach passes. The follow-up asking for amortized O(1) is the real design goal.pop and peek calls are valid → We never have to handle an empty queue for these operations, so the code can skip those guards.This approach keeps one stack in queue order at all times so that pop and peek read the oldest element directly off the top. The cost of maintaining that order is paid during push.
We designate one stack as main, where elements are stored in queue order with the oldest on top. When a new element arrives, we move everything from main to a temporary helper stack, push the new element onto the now-empty main, and move everything back. The new element ends up at the bottom of main, and the oldest element returns to the top.
main (stores elements in queue order, oldest on top) and helper (temporary storage during push).main to helper. Push x onto main. Move all elements back from helper to main.main (the top is the oldest element).main (the top is the oldest element).main is empty.Every push rearranges the entire queue, so a sequence of pushes does repeated O(n) work. The next approach defers the rearranging until a dequeue needs it.
Instead of doing the reordering work during every push, this approach defers it until a dequeue needs it. It uses two stacks with distinct roles: an input stack for pushing and an output stack for popping.
A push appends the element to the input stack and does nothing else, so it is O(1).
A pop or peek reads from the output stack. If the output stack has elements, its top is the oldest element, so we pop or peek directly. If the output stack is empty, we move every element from the input stack into the output stack first. Popping from input and pushing onto output reverses the order, which puts the oldest element on top of output.
Each element is moved at most twice over its lifetime: once onto the input stack, and once during the transfer to the output stack. Across n operations the total movement is O(n), so each operation is amortized O(1).
The transfer is the only step that touches FIFO order, so it has to be safe to defer. It is, because the transfer only runs when output is empty. While output is non-empty, its elements are already in FIFO order from a previous transfer, and any pushes since then sit in input behind them in arrival order. Those newer elements cannot become the front of the queue until every element currently in output has been served, so leaving them untransferred never reorders the queue. Once output drains, the next transfer reverses input in one pass and the elements that have waited longest end up on top.
input (receives pushed elements) and output (serves pop/peek requests).