AlgoMaster Logo

Generate Parentheses

mediumFrequency8 min readUpdated June 23, 2026

Understanding the Problem

We need to produce every possible string of length 2n made up of ( and ) characters that forms valid (balanced) parentheses. "Valid" means every opening parenthesis has a corresponding closing one, and at no point while reading left to right do we encounter more closing brackets than opening ones.

This differs from arranging n opening and n closing brackets in every possible order, because most of those arrangements are invalid. For example, )( uses one of each but is not well-formed. The challenge is to enumerate only the valid strings without generating and filtering all 2^(2n) possibilities.

One option is to build the strings character by character. At each position, we choose ( or ). If we track how many opening and closing brackets we have placed so far, we can enforce validity during construction: place ( while fewer than n of them have been used, and place ) only while the count of closing brackets is less than the count of opening brackets. That rule leads to a backtracking solution.

Key Constraints:

  • 1 <= n <= 8 keeps the input small. At n = 8 there are 1,430 valid combinations (the 8th Catalan number), and even enumerating all 2^16 = 65,536 binary strings finishes in well under a second. The small bound makes a brute-force approach viable, though better ones exist.
  • The output size is the Catalan number C(n) = C(2n, n) / (n+1). For n = 8, C(8) = 1,430. Any generation method that produces only valid strings does work proportional to this count, so the output itself dominates the running time.

Approach 1: Brute Force (Generate All and Filter)

Intuition

Generate every string of length 2n over the characters ( and ), then keep the valid ones. Each position has two choices, so there are 2^(2n) total strings. Validity is checked by scanning left to right and tracking a running balance: increment for (, decrement for ). The string is valid when the balance never goes negative and ends at zero.

This wastes most of its work. For n = 8 it builds 65,536 strings but only 1,430 are valid, so roughly 98% of the strings are discarded. With n capped at 8 it still finishes quickly.

Algorithm

  1. Generate all 2^(2n) binary strings of length 2n, where 0 maps to ( and 1 maps to ).
  2. For each string, check if it is valid: scan left to right, keeping a running balance. Add 1 for (, subtract 1 for ). If balance goes negative at any point, the string is invalid. If balance is zero at the end, it is valid.
  3. Collect all valid strings into the result.

Example Walkthrough

1Generate all strings of length 4 (n=2), check each for validity
1/6

Code

The waste comes from completing strings whose prefix is already invalid. The next approach checks validity during construction and abandons any prefix that can no longer become balanced.

Approach 2: Backtracking with Open/Close Counts

Intuition

Build the string one character at a time, but only ever place a character that keeps the prefix extendable to a valid string. Two counters carry all the state we need: open (how many ( we have placed) and close (how many ) we have placed). At each step:

  • Place ( if open < n, since opening brackets remain to be used.
  • Place ) if close < open, since there is an unmatched ( waiting to be closed.

Every string that reaches length 2n under these rules is valid, so no time is spent on dead ends. This is backtracking: make a choice, recurse, undo the choice, try the next option. The number of strings produced is exactly the Catalan number C(n).

Algorithm

  1. Start with an empty string and both open and close counters at 0.
  2. If the string length equals 2n, we have a complete valid combination. Add it to the result.
  3. If open < n, append ( and recurse with open + 1.
  4. If close < open, append ) and recurse with close + 1.
  5. Backtrack by removing the last character after each recursive call.

Example Walkthrough

1Start: current="", open=0, close=0, can only place '('
1/10

Code

This is already optimal in the sense that it produces only valid strings. A different approach builds them from a recursive structure instead: every valid string splits as ( + inner + ) + outer at the position where the first ( meets its matching ).

Approach 3: Divide and Conquer (Closure Number)

Intuition

Valid parentheses have a recursive structure that maps directly onto the Catalan recurrence. Take any valid string with n pairs. Its first character is (, and somewhere later sits the ) that matches it. Say that matching ) is at index 2k + 1 (0-indexed). Everything between them is a valid string of k pairs, and everything after it is a valid string of n-1-k pairs:

( + [valid string with k pairs] + ) + [valid string with n-1-k pairs]

The value k is the "closure number" of the first pair. Iterating k from 0 to n-1 and recursively generating all strings of k pairs and all strings of n-1-k pairs builds every valid string of n pairs.

Algorithm

  1. Base case: for n = 0, return a list containing only the empty string "".
  2. For each value of k from 0 to n-1:
    • Recursively generate all valid strings of k pairs (these go inside the first matched pair).
    • Recursively generate all valid strings of n-1-k pairs (these go after the first matched pair).
    • For each combination of inner and outer strings, create "(" + inner + ")" + outer and add it to the result.
  3. Return all generated strings.

Example Walkthrough

1n=3: decompose as '(' + inside(k) + ')' + outside(2-k) for k=0,1,2. First, generate(2)=["()()","(())"]
1/8

Code