Generate Parentheses
Master this topic with zero to advance depth.
Generate Parentheses
The Catalan Connection
The number of valid strings with n pairs of parentheses is the n-th Catalan Number: . This grows roughly as .
Validity Conditions
A prefix of a parenthesis string is valid if and only if:
- Balance: At any point, the number of closing brackets
)does not exceed the number of opening brackets(. - Target: The total number of opening brackets does not exceed
n. - Finality: The total length is
2nand the final counts of(and)are equal.
Search Space Pruning
Instead of generating all sequences and checking them, we only explore branches that satisfy the balance conditions.
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Examples
Level I: Brute Force (Generate and Validate)
Intuition
Generate all possible strings of length 2n consisting of '(' and ')'. Check each string for validity using a stack or a counter.
Use recursion to generate all sequences. For each sequence, verify if the balance ever goes negative and ends at zero.
Detailed Dry Run
n=1 Sequences: "((" (Invalid), "()" (Valid), ")(" (Invalid), "))" (Invalid).
Level II: Optimized Backtracking (Keeping Balance)
Intuition
Only add a parenthesis if it keeps the sequence valid. We only add '(' if we haven't used n of them, and only add ')' if the number of ')' is less than the number of '('.
Maintain open and close counts. If open < n, we can branch with '('. If close < open, we can branch with ')'.
Detailed Dry Run
n=2
- "(" (open=1, close=0)
- "((" (open=2, close=0)
- "(()" (open=2, close=1)
- "(())" (open=2, close=2) -> SUCCESS
- "(()" (open=2, close=1)
- "()" (open=1, close=1)
- "()(" (open=2, close=1)
- "()()" (open=2, close=2) -> SUCCESS
- "()(" (open=2, close=1)
- "((" (open=2, close=0)
Level III: Closure Number (Divide and Conquer)
Intuition
Every non-empty valid string S can be uniquely written as (A)B, where A and B are valid (potentially empty) parenthesis strings.
To generate all strings of length 2n, we iterate over all possible lengths of A. For a fixed i, where i is the number of pairs in A, we have n-i-1 pairs in B.
Detailed Dry Run
n=2
- i=0: (empty) B where B is len 1. Results: "()()"
- i=1: (len 1) empty. Results: "(())"
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.