Generate Parentheses in Python

Generating well-formed parentheses is a classic programming problem that involves creating all valid combinations of opening and closing parentheses for a given number n. For n=3, we need 3 opening and 3 closing parentheses arranged in valid patterns.

Problem Understanding

A valid parentheses combination follows these rules ?

  • Equal number of opening '(' and closing ')' parentheses
  • At any point, the number of closing parentheses should not exceed opening ones
  • All opening parentheses must be properly closed

Solution Approach

We use a recursive backtracking approach with these steps ?

  • Track the count of remaining opening and closing parentheses
  • Add an opening parenthesis if we still have some left
  • Add a closing parenthesis only if it doesn't exceed the opening ones
  • When both counts reach zero, we have a valid combination

Implementation

def generate_parentheses(n):
    """
    Generate all valid parentheses combinations for n pairs
    """
    result = []
    
    def backtrack(current, open_count, close_count):
        # Base case: we've used all parentheses
        if open_count == 0 and close_count == 0:
            result.append(current)
            return
        
        # Add opening parenthesis if available
        if open_count > 0:
            backtrack(current + "(", open_count - 1, close_count)
        
        # Add closing parenthesis if it doesn't exceed opening ones
        if close_count > open_count:
            backtrack(current + ")", open_count, close_count - 1)
    
    backtrack("", n, n)
    return result

# Test with n = 3
result = generate_parentheses(3)
for combo in result:
    print(combo)
((()))
(()())
(())()
()(())
()()()

Step-by-Step Example

Let's trace through how the algorithm works for n=2 ?

def generate_parentheses_with_trace(n):
    result = []
    
    def backtrack(current, open_count, close_count, depth=0):
        indent = "  " * depth
        print(f"{indent}Current: '{current}', Open: {open_count}, Close: {close_count}")
        
        if open_count == 0 and close_count == 0:
            result.append(current)
            print(f"{indent}? Valid combination: '{current}'")
            return
        
        if open_count > 0:
            print(f"{indent}? Adding '('")
            backtrack(current + "(", open_count - 1, close_count, depth + 1)
        
        if close_count > open_count:
            print(f"{indent}? Adding ')'")
            backtrack(current + ")", open_count, close_count - 1, depth + 1)
    
    backtrack("", n, n)
    return result

# Trace for n = 2
print("Tracing parentheses generation for n = 2:")
result = generate_parentheses_with_trace(2)
print(f"\nFinal result: {result}")
Tracing parentheses generation for n = 2:
Current: '', Open: 2, Close: 2
? Adding '('
  Current: '(', Open: 1, Close: 2
  ? Adding '('
    Current: '((', Open: 0, Close: 2
    ? Adding ')'
      Current: '(()', Open: 0, Close: 1
      ? Adding ')'
        Current: '(())', Open: 0, Close: 0
        ? Valid combination: '(())'
  ? Adding ')'
    Current: '()', Open: 1, Close: 1
    ? Adding '('
      Current: '()(',  Open: 0, Close: 1
      ? Adding ')'
        Current: '()()', Open: 0, Close: 0
        ? Valid combination: '()()'

Final result: ['(())', '()()']

Alternative Implementation

Here's a cleaner version using a class-based approach ?

class ParenthesesGenerator:
    def generate(self, n):
        self.result = []
        self._generate_helper(n, n, "")
        return self.result
    
    def _generate_helper(self, open_remaining, close_remaining, current):
        if open_remaining == 0 and close_remaining == 0:
            self.result.append(current)
            return
        
        if open_remaining > 0:
            self._generate_helper(open_remaining - 1, close_remaining, current + "(")
        
        if close_remaining > open_remaining:
            self._generate_helper(open_remaining, close_remaining - 1, current + ")")

# Test the class
generator = ParenthesesGenerator()
result = generator.generate(4)

print(f"Generated {len(result)} valid combinations for n=4:")
for i, combo in enumerate(result, 1):
    print(f"{i:2}. {combo}")
Generated 14 valid combinations for n=4:
 1. (((())))
 2. ((()()))
 3. ((())())
 4. ((()))()
 5. (()(()))
 6. (()()())
 7. (()())()
 8. (())(())
 9. (())()()
10. ()((()))
11. ()(()())
12. ()(())()
13. ()()(())
14. ()()()()

Time and Space Complexity

The algorithm has the following complexity characteristics ?

  • Time Complexity: O(4^n / ?n) - This is the nth Catalan number
  • Space Complexity: O(4^n / ?n) - For storing all valid combinations
  • Recursion Depth: O(2n) - Maximum depth of recursive calls

Conclusion

The recursive backtracking approach efficiently generates all valid parentheses combinations by carefully tracking opening and closing counts. The key insight is ensuring closing parentheses never exceed opening ones at any point in the construction process.

Updated on: 2026-03-25T07:44:54+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements