Implement a first-in-first-out queue using only stacks (LIFO structures). Support:
push(x) — push x to the back of the queue.pop() — remove and return the front element.peek() — return the front element without removing it.empty() — return whether the queue is empty.pop and peek are only called on a non-empty queue. Use only standard stack operations (push, pop/top, size/empty).
Input: push(1), push(2), peek(), pop(), empty() Output: 1, 1, false peek and pop both return 1 (the oldest); after popping, 2 remains, so empty is false.
Input: push(5), pop(), empty() Output: 5, true Push then pop returns 5, leaving the queue empty.
- 1 <= x <= 10^5 - At most 100 operations. - pop and peek are only called on a non-empty queue.
Two stacks make a queue. Pushes pile onto an input stack. When you need the front, you pour the input stack into an output stack — which reverses it, so the output stack's top is the queue's front. Refilling only when the output stack is empty makes every operation amortized O(1).
“Are pop and peek called on an empty queue?”
No — only when the queue is non-empty.
“Can I use anything besides stacks?”
No — the whole point is to build FIFO from two LIFO stacks.
I keep two stacks: an input stack for pushes and an output stack for the front.
When the output stack is empty and I need the front, I pour the whole input stack into it, which reverses the order.
Refilling only when output is empty makes each operation amortized O(1).
Worked example — push 1, push 2, peek, pop
push 1 -> input [1] (null) push 2 -> input [1,2] (null) peek -> output empty: pour -> output [2,1]; top is 1 returns 1 pop -> output [2,1] -> pop 1 -> [2] returns 1
Popping input and pushing to output flips LIFO order, so the queue's front (oldest) rises to the top of output.
If output still has elements, they're already in front-first order — don't disturb them. Refill from input only after output drains.
Every element is transferred at most once from input to output over its lifetime, so despite an occasional O(n) pour, the average per-operation cost is O(1).
Key takeaway
Two stacks: push onto input; for the front, pour input into output (reversing it) but only when output is empty. Then pop/peek are output-stack operations. Amortized O(1) per operation, since each element moves at most once.
push(x): input.push(x) move(): if output empty: while input: output.push(input.pop()) pop(): move(); return output.pop() peek(): move(); return output.top() empty(): input empty and output empty