Given a string s containing only the characters '(', ')', '{', '}', '[' and ']', determine whether it is valid.
A string is valid when every open bracket is closed by the same type of bracket, brackets close in the correct order, and every bracket has a matching partner.
Input: s = "()[]{}"
Output: true
Each pair opens and closes correctly in order.Input: s = "([)]" Output: false The brackets close in the wrong order: ')' arrives while '[' is still open.
- 1 <= s.length <= 10^4 - s consists only of the characters '()[]{}'.
A closing bracket can only match the bracket that was opened most recently and is still unclosed. That "most recent unmatched" rule is exactly last-in-first-out — a stack. Push every opener; on a closer, the top of the stack must be its partner, or the string is invalid.
“Does a closer have to match the bracket type?”
Yes — ( must be closed by ), [ by ], { by }.
“Does nesting order matter?”
Yes — ([)] is invalid even though counts match, because the closers arrive in the wrong order.
“Is a leftover open bracket valid?”
No — every opener must eventually be matched, so a non-empty stack at the end means invalid.
A closing bracket can only pair with the most recently opened, still-unmatched bracket.
That's a stack: I push every opener and, on a closer, check the top is its matching opener.
If the top doesn't match or the stack is empty I fail; at the end the stack must be empty.
Worked example — s = "{[]}"
{ push stack: {
[ push stack: { [
] top is [ ✓ pop stack: {
} top is { ✓ pop stack: (empty)
end, stack empty -> valid
Correct nesting means the most recently opened bracket must be the first to close. That last-in-first-out discipline is precisely a stack.
A closer with an empty stack (nothing to match), a closer whose top is the wrong type (mismatched pair), or leftover openers at the end (unmatched) all make the string invalid.
Each character is pushed or popped at most once, so a single left-to-right pass with an opener stack decides validity in linear time.
| Delete pairs repeatedly | Stack | |
|---|---|---|
| Idea | Erase '()','[]','{}' until nothing changes | Push openers, match each closer against the top |
| Time | O(n^2) | O(n) |
| Space | O(n) | O(n) |
Repeatedly deleting matched pairs works but rescans the string each round; the stack matches every bracket in a single pass. Full code is in the Approaches selector below.
Key takeaway
Push openers onto a stack; for each closer, the top must be its matching opener (else invalid). A valid string ends with an empty stack. The "match the nearest open" rule is last-in-first-out — one linear pass.
stack = []
for ch in s:
if ch is an opener: push ch
else:
if stack empty or top != matching opener of ch: return false
pop
return stack is empty