题目描述:
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
题源:here;完整代码:here
思路:
两个解题方案:1 考虑有效括号序列的特性,利用迭代的方法;2 考虑所有括号的可能组合,遍历所有可能。
方案1
这个解法和之前的手机按键字母组合很像(here),都是从左到右依次生长的类型。不同的是,在生长过程中,你需要考虑生成的括号序列是否合理。简单的总结为两个条件:1 “(”符号不能超过输入n;2 “)”符号的数量不能超过“)”符号。
以下是两种具体的实现方式:
实现1
vector<int> counts_old;
vector<string> addParathese(vector<string> input, int idx, int end){
vector<string> result;
vector<int> counts;
if (input.size() == 0){
result.push_back("(");
counts_old.push_back(1);
return result;
}
for (int i = 0; i < input.size(); i++){
if (counts_old[i] < end && input[i].size() < end * 2 - 1){
counts.push_back(counts_old[i]+1);
result.push_back(input[i] + "(");
}
if (input[i].size() - counts_old[i] < counts_old[i]){
result.push_back(input[i] + ")");
counts.push_back(counts_old[i]);
}
}
counts_old = counts;
return result;
}
vector<string> generateParenthesis(int n) {
vector<string> result;
if (n == 0) return result;
if (n == 1){
result.push_back("()");
return result;
}
for (int i = 0; i < n * 2; i++){
result = addParathese(result, i, n);
}
return result;
}
实现2
vector<string> result;
void backtrack(string s, int left, int right, int n){
if (s.size() == n * 2){
result.push_back(s);
return;
}
if (left < n) backtrack(s + "(", left + 1, right, n);
if (left > right) backtrack(s + ")", left, right + 1, n);
}
vector<string> generateParenthesis_1(int n){
backtrack("", 0, 0, n);
return result;
}
方案2
我们从简单的开始考虑:
n = 1: ()
n = 2: (()), ()()
我们发现,n从1到2增加的()其实只有两种选择:1 放在第一个()里面;2 放在第一个()右边。我们就根据这个特性从短到长进行迭代。但是仅仅知道这个条件是不够的,我们需要的是所有的()数量为n的序列,这就需要我们进行分解:我们让n=i+j, i从0开始遍历到n-1,表示()中间放多少个(),最后将所有的结果输出。
这是我比较喜欢的方案,除了实现简洁外,更重要的是没有了class中的全局变量。
vector<string> generateParenthesis_2(int n){
vector<string> result;
if (n == 0){
result.push_back("");
return result;
}
for (int i = 0; i < n; i++){
vector<string> left = this->generateParenthesis_2(i);
vector<string> right = this->generateParenthesis_2(n - i - 1);
for (int j = 0; j < left.size(); j++){
for (int k = 0; k < right.size(); k++){
result.push_back("(" + left[j] + ")" + right[k]);
}
}
}
return result;
}