括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。
说明:解集不能包含重复的子集。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
方法1:回溯+自底向上
List<String> res = new ArrayList<>();
int n;
public List<String> generateParenthesis(int n) {
this.n = n;
dfs("", 0, 0);
return res;
}
public void dfs(String s, int left, int right) {
if (left == n && right == n) {
res.add(s);
return;
}
if (left < n) dfs(s + "(", left+1, right);
if (right < left) dfs(s + ")", left, right+1);
}
List<String> res = new ArrayList<>();
int n;
public List<String> generateParenthesis(int n) {
this.n = n;
dfs("", 0, 0);
return res;
}
public void dfs(String s, int left, int right) {
if (s.length() == 2 * n) {
res.add(s);
return;
}
if (left < n) dfs(s + "(", left + 1, right);
if (right < left) dfs(s + ")", left, right + 1);
}
方法2:回溯+自顶向下
List<String> res = new ArrayList<>();
int n;
public List<String> generateParenthesis(int n) {
this.n = n;
dfs(new StringBuilder(), n, n);
return res;
}
public void dfs(StringBuilder sb, int left, int right) {
if (left == 0 && right == 0) {
res.add(sb.toString());
return;
}
if (left > 0) {
dfs(sb.append("("), left - 1, right);
sb.deleteCharAt(sb.length() - 1);
}
if (right > left) {
dfs(sb.append(")"), left, right - 1);
sb.deleteCharAt(sb.length() - 1);
}
}
方法3:回溯+剪枝
List<String> res = new ArrayList<>();
int n;
public List<String> generateParenthesis(int n) {
this.n = n;
dfs("", 0, 0);
return res;
}
public void dfs(String s, int left, int right) {
if (left == n && right == n) {
res.add(s);
return;
}
if (left > n || right > n) return;
if (right > left) return;
dfs(s + "(", left + 1, right);
dfs(s + ")", left, right + 1);
}