Generate Parentheses Backtracking DSA Solution - Study Chapter | QuizMaker

Generate Parentheses explained with generate-and-filter brute force, optimized valid-state backtracking, dry run, edge cases, complexity, and Python, C++, Java code.

Read
12m
Type
Chapter
Access
Free

Course

DSA Course: Interview Patterns and Problem Solving

Topic

Module 11: Recursion & Backtracking

Learning Outcome

After this lesson, you should be able to prune invalid prefixes before they are generated.

Problem Statement

Given n pairs of parentheses, generate all combinations of well-formed parentheses.

InputOutputWhy
n = 3["((()))","(()())","(())()","()(())","()()()"]Only strings where every prefix has close count <= open count are valid.

Brute Force Approach

Generate every string of length 2n made of ( and ), then filter invalid strings. This creates many impossible states.

Optimized Approach

Backtrack only through valid states: add ( while open < n, and add ) only while close < open.

Exact Pseudocode

answer = []
dfs(path, open, close):
  if length(path) == 2 * n:
    answer.add(path)
    return
  if open < n:
    dfs(path + "(", open + 1, close)
  if close < open:
    dfs(path + ")", open, close + 1)
return answer

Reference Code

class Solution:
    def generateParenthesis(self, n):
        answer = []

        def dfs(path, open_count, close_count):
            if len(path) == 2 * n:
                answer.append(path)
                return

            if open_count < n:
                dfs(path + "(", open_count + 1, close_count)
            if close_count < open_count:
                dfs(path + ")", open_count, close_count + 1)

        dfs("", 0, 0)
        return answer
class Solution {
public:
    vector<string> answer;

    void dfs(string path, int open, int close, int n) {
        if (path.size() == 2 * n) {
            answer.push_back(path);
            return;
        }

        if (open < n) dfs(path + "(", open + 1, close, n);
        if (close < open) dfs(path + ")", open, close + 1, n);
    }

    vector<string> generateParenthesis(int n) {
        dfs("", 0, 0, n);
        return answer;
    }
};
class Solution {
    private List<String> answer = new ArrayList<>();

    public List<String> generateParenthesis(int n) {
        dfs("", 0, 0, n);
        return answer;
    }

    private void dfs(String path, int open, int close, int n) {
        if (path.length() == 2 * n) {
            answer.add(path);
            return;
        }

        if (open < n) dfs(path + "(", open + 1, close, n);
        if (close < open) dfs(path + ")", open, close + 1, n);
    }
}

Sample Dry Run

StepStateResult
Startpath="", open=0, close=0Only "(" is allowed
path="("open=1, close=0Can add "(" or ")"
Invalid prefix blockedclose can never exceed openNo path starts with ")"
Length 6Valid path copiedAnswer receives one string

Complexity

MeasureValueReason
TimeO(Cn)The number of valid strings is the nth Catalan number.
SpaceO(n)The recursion path length is at most 2n.

Edge Cases

Interview Checklist

FAQs

Why is close < open required?

A closing parenthesis is valid only if there is an unmatched opening parenthesis.

Why not generate all strings first?

Most generated strings would be invalid, so pruning saves work and is clearer.

What is the core pattern?

Valid-state backtracking.

Tags

Open on QuizMaker