#22 Generate Parentheses
frequently reported atWalmartAmazonBloombergMicrosoftGoogleByteDance / TikTok
the problem
In plain words
Given n pairs of parentheses, return all well-formed (balanced) combinations.
in n = 3
out ["((()))","(()())","(())()","()(())","()()()"]
in n = 1
out ["()"]
- 1 ≤ n ≤ 8
your turn
Try it before you peek
Read the examples, say the brute force out loud, then write code: here or on LeetCode ↗. Stuck for 20 minutes? Open one hint at a time.
Solve it in the browser
LeetCode-style: complete the class. Compiled by the real javac (Java 17) and judged right here — nothing is sent anywhere.
Solutions are hidden so you can try first. Even 20 minutes of real effort makes the answer stick far better than reading it.
Marking the problem solved, or opening every hint, also shows it.
the aha
Key insight
patternBacktracking with constraint pruning
You may add '(' while open < n, and ')' only while close < open. Those two rules make every branch valid — nothing is generated and then thrown away.
solutions
From brute force to optimal
Every position is '(' or ')'; check balance at the end.
- Fill 2n slots with both choices recursively.
- At the end, scan: balance never negative and ends at 0.
2²ⁿ = 4ⁿ strings, each validated in O(n).
The char array and recursion depth (excluding output).
class Solution { public List<String> generateParenthesis(int n) { List<String> result = new ArrayList<>(); generateAll(new char[2 * n], 0, result); return result; } private void generateAll(char[] chars, int pos, List<String> result) { if (pos == chars.length) { if (valid(chars)) result.add(new String(chars)); return; } chars[pos] = '('; generateAll(chars, pos + 1, result); chars[pos] = ')'; generateAll(chars, pos + 1, result); } private boolean valid(char[] chars) { int balance = 0; for (char c : chars) { balance += c == '(' ? 1 : -1; if (balance < 0) return false; // a ')' closed nothing } return balance == 0; }}Only extend in ways that keep the prefix valid.
- Length 2n → record.
- If open < n: add '(' and recurse.
- If close < open: add ')' and recurse.
- Undo each append after its call.
Only valid strings are built: the n-th Catalan number ≈ 4ⁿ/(n^1.5·√π) of them, each O(n).
Recursion depth 2n and the builder (excluding output).
class Solution { public List<String> generateParenthesis(int n) { List<String> result = new ArrayList<>(); backtrack(n, 0, 0, new StringBuilder(), result); return result; } private void backtrack(int n, int open, int close, StringBuilder path, List<String> result) { if (path.length() == 2 * n) { // a complete string is always valid result.add(path.toString()); return; } if (open < n) { // we may still open a new pair path.append('('); backtrack(n, open + 1, close, path, result); path.deleteCharAt(path.length() - 1); } if (close < open) { // only close what is open → never invalid path.append(')'); backtrack(n, open, close + 1, path, result); path.deleteCharAt(path.length() - 1); } }}Dry run
Replace recursion with a Deque of (prefix, open, close) states. Push ')' before '(' so '(' is explored first, like the recursion.
- Push ("", 0, 0).
- Pop a state; if complete, record it.
- Otherwise push the allowed children.
Visits the same states as the recursive version.
The stack holds at most about 2n waiting states (one sibling per level), each with a prefix of up to 2n characters.
class Solution { record State(String prefix, int open, int close) {} public List<String> generateParenthesis(int n) { List<String> result = new ArrayList<>(); Deque<State> stack = new ArrayDeque<>(); // replaces the call stack stack.push(new State("", 0, 0)); while (!stack.isEmpty()) { State s = stack.pop(); if (s.prefix().length() == 2 * n) { result.add(s.prefix()); continue; } // push ')' first so '(' is popped first -> same order as the recursive version if (s.close() < s.open()) stack.push(new State(s.prefix() + ")", s.open(), s.close() + 1)); if (s.open() < n) stack.push(new State(s.prefix() + "(", s.open() + 1, s.close())); } return result; }}in the room
How to say it in the interview
talk track
- State the two rules first; the code is then four lines.
- Explain why you never need a validity check: an invalid prefix is never created.
- Name the Catalan numbers (1, 1, 2, 5, 14, 42 …) — it shows you know why the count grows like 4ⁿ/n^1.5.
- If asked "where's the stack?": recursion uses the call stack; show the explicit Deque version.
traps
- Forgetting to remove the last character after the recursive call (with a shared StringBuilder).
- Allowing ')' when close < n instead of close < open — that produces strings like ")(".
what they ask next
Follow-ups
Just count them?
That is the Catalan number C(n) = C(2n, n)/(n + 1), or a DP: C(n) = Σ C(i)·C(n−1−i).
Why a StringBuilder with undo instead of s + "("?
String concatenation copies the string every call. A shared builder with append/delete is O(1) amortized per step.
Valid Parenthesis String (LC 678) with '*' wildcards?
Greedy: track the range [lo, hi] of possible open counts; fail if hi < 0, clamp lo at 0, succeed if lo == 0 at the end.
before you submit
Edge cases to test
- n = 1 → ["()"].
- n = 8 → 1,430 strings (the 8th Catalan number), the maximum.
- A ')' with nothing open, like ")(", must never appear.
practise next
Similar problems
- #20Valid ParenthesesEasyin Stacks
- #678Valid Parenthesis StringMediumin Greedy
- #32Longest Valid ParenthesesHardin Stacks