PracticeNeetCode ↗LeetCode ↗
Given n pairs of parentheses, generate every combination of well-formed parentheses strings that can be made from them.
) when there's no unmatched ( to close.( while opens < n, and into ) while closes < opens.( used, and the count of ) used.2n, it's complete — add it to the results and return.(, recurse, then remove it (backtrack).), recurse, then remove it (backtrack).Time: O(4ⁿ / √n) — bounded by the nth Catalan number — Space: O(n) recursion depth, excluding output
def generateParenthesis(n: int) -> list[str]:
result = []
def backtrack(current: list[str], open_count: int, close_count: int) -> None:
if len(current) == 2 * n:
result.append("".join(current))
return
if open_count < n:
current.append("(")
backtrack(current, open_count + 1, close_count)
current.pop()
if close_count < open_count:
current.append(")")
backtrack(current, open_count, close_count + 1)
current.pop()
backtrack([], 0, 0)
return resultHow the solution above works, piece by piece.
backtrack builds the string one character at a time, tracking how many ( and ) it has used.2 * n characters it is complete and valid: save it.( if fewer than n have been used.) only if close_count < open_count, i.e. there is an open bracket to close. This rule alone guarantees validity.current.pop() after each recursive call undoes the choice so the same list can be reused for the next branch. The number of results is the n-th Catalan number (5 for n = 3).The full backtracking tree for n = 3:
( (allowed while fewer than n are open); going right adds ) (allowed only while it has an unmatched (). Every branch is valid by construction, so all 5 leaves are answers and nothing is ever thrown away.