数字
n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]示例 2:
输入:n = 1 输出:["()"]提示:
1 <= n <= 8
思路:
我们尝试每次递归都对字符串s追加一个'(' 或 ')',并在最后过滤掉括号不匹配的情况
1.递归终结条件:
当左括号数量left与右括号数量right不断+1,最后都等于括号对数n时,递归终止
2.处理当前层逻辑 + 下探到下一层
每递归一次都试探性的在之前基础上放一个 '(' 或 ')',对应后面括号数量: left+1 或 right +1
同时,要注意两个条件:
(1)首先应尝试在字符串 s 后添加左括号 '(' ,而不是右括号 ')'(最开始右括号不能出现在左括号之前,否则不匹配)
(2)左括号数或右括号数都不能超过最大括号对数n:if (left < n) 或 if (right < left)
Go递归版本:
// 方式1 尝试对括号数做加法
// left:【已使用】左括号数;right:【已使用】右括号数
var res []string
func generateParenthesis(n int) []string {
res = make([]string, 0)
dfs(n, 0, 0, "")
return res
}
func dfs(n, left, right int, subRes string) {
// 左括号数与右括号数都用完后
if left == n && right == n {
res = append(res, subRes)
return
}
// 优先追加左括号
if left < n {
dfs(n, left+1, right, subRes+"(")
}
// 当左括号个数多于右括号时,再追加右括号
if right < n && right < left {
dfs(n, left, right+1, subRes+")")
}
}
// 方式2 尝试对括号数做减法
// left:【剩余】左括号数;right:【剩余】右括号数
var res []string
func generateParenthesis(n int) []string {
res = make([]string, 0)
generate(n, n, "")
return res
}
func generate(left, right int, subStr string) {
if /*left == 0 &&*/ right == 0 { // 这里仅判断右括号数减为0就行
res = append(res, subStr)
return
}
// 优先添加左括号
if left > 0 {
generate(left - 1, right, subStr + "(")
}
// 若剩余右括号数 > 剩余左括号数,那么在"优先添加左括号的基础上"再加右括号
if right > 0 && right > left {
generate(left, right - 1, subStr + ")")
}
}
C++版:
class Solution {
public:
vector<string> generateParenthesis(int n) {
_generate(0, 0, n, "");
return v;
}
void _generate(int left, int right, int n, string s)
{
// 1.递归终结条件
if (left == n && right == n)
{
// cout << s << endl;
v.push_back(s);
return;
}
// 2.处理当前层逻辑 + 下探到下一层
if (left < n)
_generate(left + 1, right, n, s + '('); // 传n
if (right < left) // right < n && right < left 合并
_generate(left, right + 1, n, s + ')');
}
// 测试输出
void print()
{
for (vector<string>::iterator it = v.begin(); it != v.end(); it++) // insert delete 才可能出现迭代器失效问题
{
cout << *it << endl;
}
}
private:
vector<string> v;
};