Valid Parentheses
Verify that code brackets (), {}, and [] are properly closed and nested in order. This is the exact algorithm compilers, linters, and IDEs use to detect syntax errors in real-time.
Problem Statement
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
Examples & Constraints
- 1 <= s.length <= 10^4
- s consists of parentheses only '()[]{}'.
Stack Matching (LIFO)
Optimal ApproachPush opening brackets onto a stack. When encountering a closing bracket, pop the top element and verify it matches the expected bracket type.
We make a single pass through the string of length N. Stack pushes and pops take constant O(1) time.
In the worst case (e.g. '(((((('), the stack stores up to N opening characters simultaneously.
Underlying algorithmic logic
The Core Mental Model (Why a Stack?)
Brackets represent nested scopes—exactly like HTML tags (<div><span></span></div>) or nested function execution frames. You cannot close an outer scope while an inner scope is still active.
Crucially: the most recently opened bracket is always the first one that must be closed.
That "Last Opened, First Closed" behavior is the definition of LIFO (Last-In, First-Out), which makes a Stack the perfect data structure.
Step-by-Step Engineering Flow
- Early Parity Check (`O(1)` Fast Return): Every opening bracket demands a closing partner. If
s.lengthis odd, a complete match is mathematically impossible. We can immediately returnfalsebefore allocating any stack memory.
- Traverse and Match: Iterate through each character in the string:
- Opening bracket (
(,{,[): Push it onto the stack. We've opened a scope that expects a future closure. - Closing bracket (
),},]): - Check if the stack is already empty. If yes, we have an orphan closing bracket with nothing to pair with (e.g.,
s = "]"). Returnfalse. - Pop the top opening bracket from the stack.
- Compare: does the popped opener match the incoming closer? If there's a type mismatch (like
(paired with]), returnfalse.
- The Leftover Scope Trap: Never return
truesimply because the loop finished without an error! Considers = "(((": no mismatched closers ever occurred, yet three brackets remain unclosed. Returnstack.isEmpty()—only an empty stack guarantees all opened scopes were legitimately resolved.
Step-by-step execution walkthrough
Encountered opening bracket. Push '(' onto the stack.
Encountered nested opening bracket. Push '[' onto the stack.
Encountered closer. Pop top element '['. Matches ']' -> scope resolved.
Encountered closer. Pop top element '('. Matches ')' -> scope resolved.
String fully processed and stack is completely empty. Return true.
- •Optimal single-pass O(n) runtime
- •Directly mirrors compiler parsing & syntax highlight engines
- •Early O(1) parity check rejects 50% of invalid cases before memory allocation
- •Requires O(n) auxiliary stack memory in worst-case nested strings
Code Implementations
Ready-to-useCopy & paste production-ready solutions for Stack Matching (LIFO) in your language of choice
def is_valid(s: str) -> bool:# Fast exit: odd length cannot be fully balancedif len(s) % 2 != 0:return Falsestack: list[str] = []bracket_map = {')': '(', '}': '{', ']': '['}for char in s:if char in bracket_map:# Closing bracket: pop top opener or sentinel '#' if stack is emptytop = stack.pop() if stack else '#'if top != bracket_map[char]:return Falseelse:# Opening bracketstack.append(char)# Valid only if stack is empty (no unclosed brackets)return len(stack) == 0if __name__ == "__main__":print(f'is_valid("()[]{{}}"): {is_valid("()[]{}")}')print(f'is_valid("(]"): {is_valid("(]")}')
Understand Stack Visually
Learn the Last-In, First-Out (LIFO) stack data structure with pushing, popping, and structural queries. Test live edge cases and watch memory state transitions step-by-step.
Frequently Asked Questions
Related Logic & Algorithm Problems
Two Sum
Find the two numbers in an array that sum up to a target value. The quintessential problem for learning how to trade memory for speed using a Hash Map.
Binary Search
Locate a target value in a sorted array in O(log n) logarithmic time. Like opening a dictionary in the middle, each comparison eliminates half the remaining items.
Reverse Linked List
Reverse the directional arrows of a singly linked list in-place. The classic test of reference manipulation and memory pointer management.