题目:给定一个数字n, 生成所有可能的并且有效的括号组合。
有效组合示例:"()()()", "(())()", "((()))"
无效组合示例:")()(", "()))("
思路:
设置一个left变量以及一个right变量,分别记录当前左括号的右括号有多少个,接着利用回溯的思想,每次递归都进行如下尝试:
1. 如果当前left和right变量同时等于n,则表示找到其中一种排列。
2. 如果left等于n但right不等于n,则后续只能出现右括号。
3. 如果left和right都同时小于n,则后续左右括号都合法,这时我们需要再次递归分别加上左,右括号。(这里要注意right必须小于left才能添加右括号,否则会出现右括号在前的情况)。
注:一定优先添加左括号,因为无论如何第一个字符都不可以出现右括号。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<>(); // 结果集
doGenerate(n, res, new StringBuilder(), 0, 0);
return res;
}
public void doGenerate(int n, List<String> res, StringBuilder sb, int left, int right) {
// 首先判断是否还能继续添加左括号
if (left == n && right == n) {
// 找到一种排列,递归结束
res.add(sb.toString());
return;
}
if (left == n) {
// 不能再加左括号
sb.append(')');
doGenerate(n, res, sb, left, right + 1);
sb.delete(sb.length() - 1, sb.length());
} else {
// 一定要优先添加左括号
sb.append('(');
doGenerate(n, res, sb, left + 1, right);
// 回溯
sb.delete(sb.length() - 1, sb.length());
// 需要先判断right是否小于left,否则可能出现右括号在前的情况。
if (right < left) {
// 添加右括号
sb.append(')');
doGenerate(n, res, sb, left, right + 1);
sb.delete(sb.length() - 1, sb.length());
}
}
}
}