Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources
Generate Parentheses

Generate Parentheses

Problem Statement

Given an integer n, generate all valid combinations of n pairs of parentheses. A combination is valid if every opening parenthesis '(' has a matching closing parenthesis ')', and the sequence is well-formed (no closing before opening). This medium-level problem uses recursion and backtracking to build balanced strings—think of it as crafting perfectly nested expressions!

Example

Input: n = 3

Output: ["((()))", "(()())", "(())()", "()(())", "()()()"] (all 5 valid ways for 3 pairs)

Input: n = 1

Output: ["()"] (only one way for 1 pair)

Code

Java
Python
JavaScript
public class Solution {
    public List generateParenthesis(int n) {
        List result = new ArrayList<>();
        backtrack(result, "", 0, 0, n);
        return result;
    }
    
    private void backtrack(List result, String current, int open, int close, int max) {
        if (current.length() == max * 2) {
            result.add(current);
            return;
        }
        if (open < max) {
            backtrack(result, current + "(", open + 1, close, max);
        }
        if (close < open) {
            backtrack(result, current + ")", open, close + 1, max);
        }
    }
}
            
def generate_parenthesis(n):
    def backtrack(current, open_count, close_count):
        if len(current) == n * 2:
            result.append(current)
            return
        if open_count < n:
            backtrack(current + "(", open_count + 1, close_count)
        if close_count < open_count:
            backtrack(current + ")", open_count, close_count + 1)
    
    result = []
    backtrack("", 0, 0)
    return result

# Example usage
print(generate_parenthesis(3))  # ["((()))", "(()())", "(())()", "()(())", "()()()"]
print(generate_parenthesis(1))  # ["()"]
            
function generateParenthesis(n) {
    function backtrack(current, open, close) {
        if (current.length === n * 2) {
            result.push(current);
            return;
        }
        if (open < n) {
            backtrack(current + "(", open + 1, close);
        }
        if (close < open) {
            backtrack(current + ")", open, close + 1);
        }
    }
    
    let result = [];
    backtrack("", 0, 0);
    return result;
}

// Example usage
console.log(generateParenthesis(3)); // ["((()))", "(()())", "(())()", "()(())", "()()()"]
console.log(generateParenthesis(1)); // ["()"]
            

Explanation

  • Base Case: When string length equals 2n (n pairs), add it to the result.
  • Choices: Add an opening '(' if fewer than n are used, or a closing ')' if fewer than open.
  • Backtracking: Build the string incrementally, exploring all valid paths.
  • Flow Example (n=2): "" → "(" → "((" → "(()" → "(())"; backtrack to "()" → "()(" → "()()".
  • Validity: Ensures well-formedness by only closing when there’s an unmatched opening.

Note

Time complexity is O(4^n / √n), the nth Catalan number, representing valid combinations. Space complexity is O(n) for the call stack plus O(4^n / √n) for the result. It’s a elegant dance of balance!