Algorithm

Valid Parentheses

Stacks & Queues Pattern

Valid Parentheses

Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. An input string is valid if: open brackets are closed by the same type of brackets, open brackets are closed in the correct order, and every close bracket has a corresponding open bracket of the same type.

CONSTRAINTS
  • 1 <= s.length <= 10⁴
  • s consists of parentheses only: ()[]{}
  • A valid string always has even length (every open needs one close)
EXAMPLE 1
Input: s = "()"
Output: true
Single matching pair.
EXAMPLE 2
Input: s = "()[]{}"
Output: true
Three independent pairs in sequence — no nesting.
EXAMPLE 3
Input: s = "{[()]}"
Output: true
Correct nesting: innermost () closes first, then [], then {}.
EXAMPLE 4
Input: s = "(]"
Output: false
Open '(' cannot be closed by ']'. Type mismatch.
What if the string is empty?
An empty string has no unmatched brackets and is valid. The stack will be empty at the start and remains empty — return true.
Can the string have an odd number of characters?
An odd-length string can never be valid — every open bracket needs exactly one close bracket. You can return false immediately if s.length is odd.

A first instinct is to count. If the string has as many ( as ), isn't it balanced? Try ([)]. Two opens, two closes, the counts are perfectly equal — yet it is nonsense: the ( ends up closed by ]. Counting throws away the one thing that actually decides this problem: order — specifically, which bracket is still open right now.

Look at what a valid string really demands. When you hit a closing bracket, it can only legally close the opening bracket that is still unmatched and was opened most recently. Read { [ ( and then a ) arrives: the only opener it may match is the (, because that's the newest one you haven't closed. Everything older is frozen behind it — you cannot touch the { until the [ and ( sitting inside it are closed first.

So as you scan left to right, you need a running memory of "brackets opened but not yet closed", and you always deal with the newest one first: add to one end, remove from that same end, newest on top. That structure has a name — a stack.

A stack is just a pile you can only touch from the top. Two moves: push (put one on top) and pop (take the top one off). The last thing pushed is the first thing popped — "Last In, First Out", or LIFO. A stack of plates works the same way: you always take the top plate, never reach into the middle.

Here is the whole method. Walk the string one character at a time:
- An opening bracket → push it. You've just recorded a promise to close it later.
- A closing bracket → look at the top of the stack. If it's the matching opener, pop it (promise kept). If it isn't — wrong type, or the stack is empty — the string is invalid; stop.

At the very end the stack must be empty. Anything still on it is an opener that was never closed.

python
def is_valid(s):
    match = {')': '(', ']': '[', '}': '{'}
    stack = []
    for ch in s:
        if ch in match:                      # a closing bracket
            if not stack or stack.pop() != match[ch]:
                return False                 # closes nothing, or wrong type
        else:                                # an opening bracket
            stack.append(ch)
    return not stack                         # valid only if nothing left open
Crucial Notethree different failures all mean "invalid", and it's easy to forget one. A closing bracket when the stack is empty means you're closing something never opened () or (]}). A closing bracket whose top doesn't match means a type clash ((]). And a non-empty stack at the end means an opener was never closed ((((). The first two live in the closing branch above; the third is the final return not stack. Drop any one of them and specific inputs slip through.
Worked Example:why ([)] is invalid
- ( — opener, push. Stack: [ ( ]
- [ — opener, push. Stack: [ (, [ ]
- ) — closer. Top is [, but ) needs (. Mismatch → return False.
The counts were equal, but the newest open bracket was [, and ) cannot close a [. The stack caught exactly what counting missed.
When to reach for a stack

This tiny problem is the cleanest example of the one situation a stack was built for: whenever the most recently seen, still-unfinished thing is the one you must handle first. Notice the shape of the reasoning — each opener created an obligation, obligations had to be resolved newest-first, and older ones waited underneath, untouched. Any problem with that shape wants a stack.

Signals to watch for in an unfamiliar problem statement, each tied to that newest-first shape:
- Matching or pairing things that can nest — brackets, tags, quotes.
- The words "nested", "innermost first", "balanced", "valid order".
- Undo / go back one step — the last action is the first to reverse (you'll see this in Simplify Path, where .. cancels the last folder).
- Deferred evaluation — you can't finish the current thing until a newer, inner thing finishes first (Evaluate RPN, Decode String, Basic Calculator II all live here).

The invariant to keep in your head — and the thing to look for in any candidate problem — is this: the stack always holds exactly the currently-open, not-yet-resolved items, oldest at the bottom, newest on top. If you can describe your problem's "open items" that way, the stack writes itself; the only decisions left are what you push, when you pop, and what counts as a "match".

And the boundary: if the thing you must handle next is the oldest waiting item instead of the newest, a stack is the wrong tool — you want a queue (First In, First Out). Serving people in arrival order or exploring a graph breadth-first flips the rule.

Interactive Strategy Visualization
BALANCED STRUCTURE INSIGHT

Last-In-First-Out Verification

{
[
]
}
Balance Stack
Current State
?
Processing segment...
Execution Trace

Start with an empty stack.

The Symmetry Principle

A stack naturally ensures that the most recently opened context is the first to be closed.

O(N²) Repeatedly Strip Pairs
O(N) One Pass · O(N) Stack of Open Brackets