题目相关
题目链接
LeetCode中国,
https://leetcode-cn.com/problems/generate-parentheses/
。
LeetCode中国,
https://leetcode-cn.com/problems/bracket-lcci/
。
两题是一样的。
题目描述
括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。说明:解集不能包含重复的子集。
示例
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
题目分析
LeetCode 给出本题难度中等。
题意分析
根据给定的长度 n,构造所有可能的跨号组合。
样例数据分析
略。
算法设计
这题一看就知道是一个搜索回溯问题。可以参考我以前写的回溯题解。
既然已经确定是一个回溯题目,哪么我们直接可以套用回溯模板。
搜索函数设计
设计搜索函数的核心就是确定要几个参数。碰到这个问题,我们先不管三七二十一,将函数写上去,然后再逐步确定需要几个参数。
1、一个字符串,用来表述当前生成的数据是怎么样的。
2、一个数字,表示现在已经有几个左括号。
3、一个数字,表示现在已经有几个右括号。
4、一个数字,表示目标搜索字符串长度。
5、一个参数,表示已经有几个解了。
由于 C++ 不建议函数参数超过 4 个,所以我们可以将第五个参数优化,使用类的变量来实现。或者还可以进一步优化,将目标字符串长度也优化了。这里我们就不优化第四个参数了。这样,我们就可以设计出一个带有 4 个参数的搜索函数,原型如下。
/*
第一个参数:当前的字符串
第二个参数:左括号数量
第三个参数:右括号数量
第四个参数:目标长度
*/
void dfs(string path, int lpos, int rpos, int n);
搜索返回条件
自然是 lpos+rpos 和 n 进行比较。
回溯
本题的难度所在。
以前回溯的模板基本如下。
path.push_back("(");
dfs(xxxx);
path.pop_back();
本题的回溯和以前不大一样,由于是左右括号,所以不能这样回溯。只能通过判断左括号和右括号来解决。具体看代码。
AC 参考代码
class Solution {
public:
vector<string> ans;//答案
vector<string> generateParenthesis(int n) {
string path;//当前生成的字符串
dfs(path, 0, 0, n);
return ans;
}
/*
第一个参数:当前的字符串
第二个参数:左括号数量
第三个参数:右括号数量
第四个参数:目标长度
*/
void dfs(string path, int lpos, int rpos, int n) {
if (lpos>=n && rpos>=n) {
cout << path << endl;
ans.push_back(path);
return;
}
if (lpos<n) {
//左边括号还有,继续加
dfs(path+"(", lpos+1, rpos, n);
}
if (rpos<n && lpos>rpos) {
dfs(path+")", lpos, rpos+1, n);
}
}
};
只能说通过了题目,算法设计一般吧。先将就一下。