150NeetCode 150

24.Generate Parentheses

MediumStack ยท 4/7

Problem

Given an integer n, return all combinations of n pairs of parentheses that are well-formed (every '(' is closed by a later ')', and no prefix closes more than it opens). The order of the output does not matter.

Examples

Input:  n = 3
Output: ["((()))", "(()())", "(())()", "()(())", "()()()"]
Input:  n = 1
Output: ["()"]

Constraints

  • 1 <= n <= 8

๐Ÿ’ก Key Insight

A partial string can still become valid iff (1) it has used at most n opening brackets and (2) it never has more ')' than '('. So build the string one character at a time and only add '(' while open < n, and only add ')' while close < open. Every path of this search ends in a valid answer โ€” no wasted work on dead branches.

Brute Force (Generate and Validate)

TimeO(2^(2n) ยท n)SpaceO(n)

Intuition

Each position of a length-2n string is either '(' or ')', giving 2^(2n) strings. Generate them all and keep those that are balanced (running balance never negative and ends at zero).

Algorithm

  1. Recursively fill a char[2n] with every combination of '(' and ')'.
  2. When full, check validity with a running balance counter.
  3. Add valid strings to the result.

Visualization

n = 1 โ†’ all length-2 strings:
"((" balance ends 2      โœ—
"()" balance 1 โ†’ 0       โœ“
")(" balance goes -1     โœ—
"))" balance goes -1     โœ—

Code

java
import java.util.ArrayList;
import java.util.List;

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList<>();
        generate(new char[2 * n], 0, result);
        return result;
    }

    private void generate(char[] current, int pos, List<String> result) {
        if (pos == current.length) {
            if (isValid(current)) {
                result.add(new String(current));
            }
            return;
        }
        current[pos] = '(';
        generate(current, pos + 1, result);
        current[pos] = ')';
        generate(current, pos + 1, result);
    }

    private boolean isValid(char[] s) {
        int balance = 0;
        for (char c : s) {
            balance += (c == '(') ? 1 : -1;
            if (balance < 0) {
                return false; // closed more than opened
            }
        }
        return balance == 0;
    }
}

Complexity

  • Time: O(2^(2n) ยท n) โ€” every one of the 4^n strings is built and validated in O(n).
  • Space: O(n) โ€” recursion depth 2n (excluding the output).

Complexity Comparison

Approach Time Space (excl. output)
Brute Force (generate + validate) O(4^n ยท n) O(n)
Dynamic Programming O(4^n / โˆšn) O(4^n / โˆšn)
Backtracking O(4^n / โˆšn) O(n)

Common Pitfalls

  • Allowing ')' when close < n instead of close < open โ€” produces strings like ")(".
  • Forgetting to remove the last character after recursing when sharing a StringBuilder โ€” later branches see stale characters.
  • Adding sb itself (not sb.toString()) to the result list โ€” every entry would point to the same mutating builder.
  • Assuming a specific output order; LeetCode accepts any order.