22-生成括号
题目描述
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
解题思路
暴力破解法
生成所有 2^{2n} 个
'('
和')'
字符构成的序列。然后,我们将检查每一个是否有效。为了检查序列是否为有效的,我们会跟踪
平衡
,也就是左括号的数量减去右括号的数量的净值。如果这个值始终小于零或者不以零结束,该序列就是无效的,否则它是有效的。
回溯法
与暴力破解法比较,回溯法不是无脑添加括号生成序列,而是只有当前的序列是平衡的时候,我们才往序列尾部继续添加'('
或者')'
。我们可以维护两个变量int l
和int r
来记录当前左括号和右括号的数目,通过左右括号数目的比较,来判断当前序列是否是平衡的。
如果还有空位,我们可以先放一个左括号;如果右括号的数目不超过左括号的数目,就添加右括号寻求平衡。
Java 实现
public class GenerateParentheses {
public List<String> generateParenthesis (int n) {
List<String> ans = new ArrayList<>();
backtrack(ans, "", 0, 0, n);
return ans;
}
private void backtrack (List<String> ans, String cur, int l, int r, int max) {
if (cur.length() == 2 * max) {
ans.add(cur);
return;
}
if (l < max)
backtrack(ans, cur + "(", l + 1, r, max);
if (r < l) // 保证平衡
backtrack(ans, cur + ")", l, r + 1, max);
}
}
心得体会
这一题的回溯算法思想体现在:某一次递归添加括号达到平衡后,需要回到这一次递归的头部,寻找平衡,继续添加括号。