Check whether all brackets close in the correct order.
Start with the concrete trace below. It shows the state the algorithm must carry as it runs.
Problem trace
Valid Parentheses: A closing bracket is valid only when it removes its matching newest unmatched opening bracket.
Input and goalCheck whether all brackets close in the correct order.
Initialize an empty stackBefore scanning ([{}]), there is no unmatched opening bracket.
emptytop
input([{}])layoutbottom to topcurrentbefore index 0actioninitialize
Push the first openingAt index 0, ( is not a closing key, so the implementation appends it.
(top
input([{}])layoutbottom to topcurrentindex 0: (actionpush (
Push the nested openingAt index 1, [ is newer unfinished work and sits above (.
([top
input([{}])layoutbottom to topcurrentindex 1: [actionpush [
Push the innermost openingAt index 2, { becomes the only opening that the next closer may finish.
([{top
input([{}])layoutbottom to topcurrentindex 2: {actionpush {
Match the curly pairAt index 3, } expects {. pop() returns {, so the scan may continue.
([top
input([{}])layoutbottom to topcurrentindex 3: }actionpop {; expected {
Match the square pairAt index 4, ] expects [. pop() returns [, preserving correct nesting.
(top
input([{}])layoutbottom to topcurrentindex 4: ]actionpop [; expected [
Match the outer pairAt index 5, ) expects (. pop() returns (, leaving no unfinished opening.
emptytop
input([{}])layoutbottom to topcurrentindex 5: )actionpop (; expected (resulttrue
Recognize it
Use this pattern when nested delimiters must close in reverse opening order and each closer must validate the most recent unfinished opener.
Keep true
After each processed character, the stack contains exactly the unmatched opening brackets from the processed prefix, ordered oldest at the bottom and newest at the top.
Reuse it
For tags, expression delimiters, and nested scopes, store only unfinished openers and let each closer inspect the newest one; an empty stack at the end proves completion.
Read it this way: Before scanning ([{}]), there is no unmatched opening bracket. Step through the frames to watch the state change. The last frame shows the answer or the stopping condition.
Pattern: Stack.
Simple idea: Save opening brackets. A closing bracket must match the newest opening
bracket.
def valid_parentheses(text: str) -> bool: opening: list[str] = [] matching = {")": "(", "]": "[", "}": "{"} for char in text: if char not in matching: opening.append(char) elif not opening or opening.pop() != matching[char]: return False return not opening