Run it
FIFO through interleaved operations, which is the part worth checking.
The cost of the emptiness check, measured on the same workload.
The eager version that pours back and forth on every call does the same job, but far more of the work.
One dequeue can still be O(n) - amortised is a claim about the total.
Why reversing twice gives FIFO
A stack reverses what you put into it. Pour one stack into another and you have reversed it again, which restores the original order — so the item pushed first ends up on top of the second stack, which is exactly the front of a queue.
That is the whole trick, and it is worth stating in one sentence in an interview: the inbox has them newest-first, the outbox has them oldest-first, and pouring is what converts between the two.
The emptiness check is the entire complexity argument
The naive version pours on every dequeue — and, to keep enqueue working, pours back afterwards. That is O(n) per call and O(n²) for n dequeues. The editor below measures it: 400 operations cost 160,000 moves that way, against 400 the right way.
Pouring only when the outbox is empty means each element crosses once in its entire life. Total moves for n items is n, so the average cost per dequeue is constant even though one individual dequeue can touch every element. That is amortised O(1), and the distinction between "amortised O(1)" and "O(1) worst case" is what the follow-up question is about.
When amortised is not good enough
Amortised bounds are about totals, and some systems care about the worst single call. A real-time audio callback or a request with a latency budget cannot afford the one dequeue that moves ten thousand items, even if the average is fine.
The honest answer is that this structure cannot fix that — and naming the alternatives is what a strong answer does. Move a constant number of items per operation instead of all of them (incremental rebuilding), or use a structure that is O(1) worst case outright, which in Python is collections.deque. Which leads to the real-world footnote: nobody builds a queue from two stacks in production. The question is about reasoning, and it is fair to say so while still answering it.
The mirror question
"Now implement a stack using two queues." It is the same idea and strictly worse: one of the two operations has to become O(n), because a queue gives you the wrong end and no amount of shuffling amortises away. Either push moves everything into the second queue behind the new item, or pop moves n−1 items across to reach the last one.
There is no trick that makes both O(1) here, and saying that directly is the right answer — the asymmetry between the two questions is the thing being tested.
Edge cases to raise
Volunteering these is most of what separates a correct answer from a good one.
Dequeue from empty. The outbox is empty and so is the inbox, so the pour moves nothing and the pop raises. Check it explicitly rather than letting an IndexError escape from an internal list.
peek() needs the same pour. Forgetting the emptiness check there is the standard bug in the extension, and it returns the newest item instead of the oldest.
Nobody ships this. collections.deque is O(1) at both ends and is what production code uses. Saying that while still answering the question shows you know why it is being asked.