Lesson 48 of 250
22. Generate Parentheses
NeetCode: Generate Parentheses · LeetCode: 22. Generate Parentheses · Difficulty: Medium
Given n pairs of parentheses, return every well-formed combination.
Example
Input: n = 3
Output: ["((()))", "(()())", "(())()", "()(())", "()()()"]Brute force: generate all strings, keep the valid ones
There are 2^(2n) strings of ( and ). Build them all and filter with the balance check. The recursion appends one character to a shared StringBuilder, recurses, then removes the character with setLength. out.add(current.toString()) copies the builder, so later changes do not alter stored results. A List<String> prints as [((())), ...] without quotes.
import java.util.ArrayList;
import java.util.List;
class Solution {
private boolean isValid(CharSequence s) {
int balance = 0;
for (int i = 0; i < s.length(); i++) {
balance += s.charAt(i) == '(' ? 1 : -1;
if (balance < 0) {
return false;
}
}
return balance == 0;
}
private void build(StringBuilder current, int len, List<String> out) {
if (current.length() == len) {
if (isValid(current)) {
out.add(current.toString());
}
return;
}
for (char c : new char[]{'(', ')'}) {
current.append(c);
build(current, len, out);
current.setLength(current.length() - 1); // undo the append
}
}
public List<String> generateParenthesis(int n) {
List<String> out = new ArrayList<>();
build(new StringBuilder(), 2 * n, out);
return out;
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.generateParenthesis(3));
System.out.println(sol.generateParenthesis(1));
}
}[((())), (()()), (())(), ()(()), ()()()]
[()]Time: O(2^(2n) · n). Space: O(n) for the recursion plus the output.
Optimal: backtracking that never builds an invalid prefix
Track how many ( and ) have been used. Add ( while fewer than n are used, and add ) only while fewer ) than ( have been used, so the prefix never goes negative. Every string reached at length 2n is valid, so no filter is needed and dead ends are never explored.
import java.util.ArrayList;
import java.util.List;
class Solution {
private void backtrack(int open, int close, int n, StringBuilder current, List<String> out) {
if (current.length() == 2 * n) {
out.add(current.toString());
return;
}
if (open < n) {
current.append('(');
backtrack(open + 1, close, n, current, out);
current.setLength(current.length() - 1);
}
if (close < open) {
current.append(')');
backtrack(open, close + 1, n, current, out);
current.setLength(current.length() - 1);
}
}
public List<String> generateParenthesis(int n) {
List<String> out = new ArrayList<>();
backtrack(0, 0, n, new StringBuilder(), out);
return out;
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.generateParenthesis(3));
System.out.println(sol.generateParenthesis(1));
}
}[((())), (()()), (())(), ()(()), ()()()]
[()]Time: O(4^n / √n), the n-th Catalan number of results, each built in O(n). Space: O(n) recursion depth beyond the output.
