Build all valid parentheses combinations by backtracking: add ( while you still have opening brackets left, add ) only when it would not overtake the open count. This prunes the decision tree to only valid states.
Given a number n, return all combinations of n pairs of well-formed parentheses. For n=2 the answer is ["(())", "()()"]. For n=3 there are 5 valid strings: ["((()))", "(()())", "(())()", "()(())", "()()()"]. Order within the output does not matter.
open (how many ( placed) and close (how many ) placed). You may add ( whenever open < n, and ) whenever close < open. These two rules together guarantee every branch stays valid — no backtracking over invalid states, just construction of correct ones.backtrack('', 0, 0) — empty string, zero opens, zero closes.cur.length === 2 * n, push to result and return. Every valid combination has exactly 2n characters.(. If open < n, recurse with open + 1. We still have opening brackets to spend.). If close < open, recurse with close + 1. Closing only when there is an unmatched open prevents invalid states.n opens or let closes overtake opens, no valid string can follow, so you simply never go there.The recursion stack depth is 2n (max string length), so auxiliary space is O(n) excluding the output. The output itself is O(n · Cₙ) for the same reason.
2. Call backtrack('', 0, 0).1▶function generateParenthesis(n: number): string[] {2▶ const result: string[] = [];34 function backtrack(cur: string, open: number, close: number): void {5 if (cur.length === 2 * n) {6 result.push(cur);7 return;8 }9 if (open < n) {10 backtrack(cur + '(', open + 1, close);11 }12 if (close < open) {13 backtrack(cur + ')', open, close + 1);14 }15 }1617▶ backtrack('', 0, 0);18 return result;19}
function generateParenthesis(n: number): string[] {
const result: string[] = [];
function backtrack(cur: string, open: number, close: number): void {
if (cur.length === 2 * n) {
result.push(cur);
return;
}
if (open < n) {
backtrack(cur + '(', open + 1, close);
}
if (close < open) {
backtrack(cur + ')', open, close + 1);
}
}
backtrack('', 0, 0);
return result;
}2 * n it is complete and valid (the two guards below prevent any invalid state from ever reaching this point). Push and return.open < n. We still have unused opens. Recurse with open + 1 and close unchanged.close < open, meaning there is at least one unmatched open bracket. This single condition makes every produced string valid.C(n) = (2n choose n) / (n+1) — it grows exponentially, so you cannot do better than O(Cₙ) for output-sensitive enumeration.(cur, open, close) tuples. The recursion stack becomes a data structure, logic stays the same.C[i] = sum(C[j] * C[i-1-j]) for j in 0..i-1.function generateParenthesis(n: number): string[] {
const result: string[] = [];
function backtrack(cur: string, open: number, close: number): void {
if (cur.length === 2 * n) {
result.push(cur);
return;
}
if (open < n) {
backtrack(cur + '(', open + 1, close);
}
if (close < open) {
backtrack(cur + ')', open, close + 1);
}
}
backtrack('', 0, 0);
return result;
}Enumerate every length-2n string over ( and ), then keep only the balanced ones — validate at the end instead of pruning during construction.
function generateParenthesis(n: number): string[] {
const result: string[] = [];
// A string is valid if the running balance never goes negative
// and ends at zero.
function isValid(s: string): boolean {
let bal = 0;
for (const ch of s) {
bal += ch === '(' ? 1 : -1;
if (bal < 0) return false;
}
return bal === 0;
}
// Build all 2^(2n) sequences of '(' and ')'.
function build(cur: string): void {
if (cur.length === 2 * n) {
if (isValid(cur)) result.push(cur);
return;
}
build(cur + '(');
build(cur + ')');
}
build('');
return result;
}2²ⁿ bracket strings even though only Cₙ ≈ 4ⁿ / n^(3/2)are valid — the vast majority are generated only to be thrown away. The two guards (open < n, close < open) prune invalid prefixes eagerly so only valid strings are ever built.| "all valid combinations" + bracket/structure type | backtracking + guards |
| enumerate strings with a local validity invariant | build-and-prune, not generate-and-filter |
| count of valid parenthesizations | Catalan number formula or DP |
| check if a single string is valid parens | stack: push open, pop on match |
function generateParenthesis(n: number): string[] {
const result: string[] = [];
function backtrack(cur: string, open: number, close: number): void {
if (cur.length === 2 * n) { result.push(cur); return; }
if (open < n) backtrack(cur + '(', open + 1, close);
if (close < open) backtrack(cur + ')', open, close + 1);
}
backtrack('', 0, 0);
return result;
}open < n — you still have unplaced opening brackets.generateParenthesis(n)?n=2. Which of the following is NOT in the output?generateParenthesis(3) return?