Generate Parentheses
You're given an integer n. Return every string made of n "(" characters and n ")" characters that is well-formed: reading left to right, each ")" closes an earlier "(" that is still open, and every "(" is closed by the end. Each string has length 2n and must appear exactly once. The list may be in any order.
Examples
n = 3 returns ["((()))","(()())","(())()","()(())","()()()"]
These are the only five ways to arrange three matched pairs. A string like "())(()" is left out because its third character closes a pair that was never opened.
n = 1 returns ["()"]
With a single pair, "()" is the only option, since ")(" closes before anything is open.
Constraints
- 1 <= n <= 8
Hints
Every valid string is built by appending either '(' or ')', when is each of those legal?
Backtrack tracking how many open and close parens have been used so far.
Recurse with (path, open, close). If path.length == 2n, record it. Otherwise, if open < n, append '(' and recurse; if close < open, append ')' and recurse. Pop after each branch.
Drill This: Your Approach First
Approach
Build strings one character at a time and only make moves that keep the prefix valid. You may add "(" while fewer than n have been used, and ")" only while close < open, so every ")" has an open "(" to match. A path that reaches length 2n is therefore complete and valid, so record it. Invalid prefixes are never extended, so the work tracks the number of answers: the n-th Catalan number, roughly 4^n / n^1.5 strings of length 2n.
Time
O(4^n / sqrt(n))
Space
O(n)
Pitfall
Solutions
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) {
result.add(path.toString());
return;
}
if (open < n) {
path.append('(');
backtrack(n, open + 1, close, path, result);
path.deleteCharAt(path.length() - 1);
}
if (close < open) {
path.append(')');
backtrack(n, open, close + 1, path, result);
path.deleteCharAt(path.length() - 1);
}
}
}class Solution:
def generateParenthesis(self, n: int):
result = []
def backtrack(open_c, close_c, path):
if len(path) == 2 * n:
result.append("".join(path))
return
if open_c < n:
path.append('(')
backtrack(open_c + 1, close_c, path)
path.pop()
if close_c < open_c:
path.append(')')
backtrack(open_c, close_c + 1, path)
path.pop()
backtrack(0, 0, [])
return result