Prompt
Given a string of parentheses (){}[], determine if the order is valid (balanced). Every opening bracket must have a matching closing bracket in the correct order.
Solution
This is the introductory stack problem, and the pattern matters far beyond brackets: any "most recent open thing must close first" structure — nested tags, expression parsers, editor undo scopes — is LIFO, and a stack is its data structure. Push every opener; on a closer, pop and demand it matches. O(n) time, O(n) space worst case (all openers).
Why counting fails: tracking three counters catches "(()" but not "([)]" — counts balance while nesting order is wrong. Order is exactly what the stack encodes and counters throw away. That's the trap the interviewer sets with the "([)]" test.
Two ends of the string carry their own bugs:
- Closer on an empty stack:
stack.pop()returnsundefined, which fails thepairs[c] !== ...comparison — so"]"correctly returns false with no explicit emptiness check. Know why that works; it looks accidental otherwise. - Leftover openers:
"((("survives the loop, so the final answer must bestack.length === 0, nottrue.
The pairs map (closer → opener) keeps the loop to one comparison instead of a three-way conditional.
Red flag: returning true after the loop without checking the stack is empty — unclosed openers pass silently. Counter-based solutions are the deeper miss: they don't model nesting at all.
Say it: "Brackets are LIFO, so I push openers and pop on closers — mismatch or a non-empty stack at the end means invalid, all in O(n)."