The "Generate Parentheses" problem challenges us to produce all valid combinations of n
pairs of parentheses.
A combination is considered valid if every opening parenthesis has a matching closing one and they are properly nested.
For example, when n = 3
, a valid result includes combinations like "((()))"
, "(()())"
, and "()()()"
.
A naive approach would be to generate every possible string of 2n
characters composed of '('
and ')'
, then filter out the invalid ones.
However, that approach results in 22n
combinations to check, which is extremely inefficient for larger n
.
Instead, we leverage backtracking to generate only valid sequences directly.
Backtracking is a recursive strategy where we build up a partial solution, and as soon as we detect that it cannot lead to a valid result, we backtrack. In this problem, the key is to keep track of how many open and close parentheses have been added so far.
We begin with an empty list sol
that will be used to build each combination character by character.
At each recursive call, we make one of two decisions:
open < n
), we can safely add a '('
.close < open
), we can add a ')'
to close a group.
We continue this process recursively until the length of the built string is 2n
. At that point, we’ve formed a valid combination and add it to the result list.
The total number of valid combinations corresponds to the nth Catalan number, which grows rapidly:
C(n) = (2n)! / ((n + 1)! * n!)
.
Thus, the time complexity is O(C(n) * n), since we spend O(n) time to construct each string of length 2n
.
The space complexity is also O(C(n) * n) to store the output and support the recursive call stack.
The "Generate Parentheses" problem is a perfect example of efficient recursive construction using constraints. Instead of generating every possible combination and filtering, we guide our recursive steps based on rules that define validity. This dramatically reduces unnecessary computation and provides a deeper understanding of how constraints can guide exploration.