Valid parentheses
A stack. Push every opener; on a closer, pop and check it matches. Two things fail: a closer with nothing to match, and a closer matching the wrong opener. A third check at the end catches openers that were never closed — miss it and "(((" passes.
Overview
Why a stack and not a counter
With one bracket type, counting works: increment on open, decrement on close, fail if it goes negative or ends non-zero. With several types it does not — "([)]" has balanced counts and is wrong.
A stack captures the thing a counter loses: not just how many are open, but which, and in what order. Nesting is inherently last-in-first-out, which is exactly what a stack is.
Step through it
What to watch
- The stack depth is the current nesting level.
- A match pops; a mismatch stops immediately.
- The final empty-stack check is what rejects
"(((".
Say this out loud
"Stack. Push openers, pop and compare on closers, and at the end the stack must be empty. Three failure modes: wrong match, closer with an empty stack, and leftovers at the end."