一、题目
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]
二、题解
1.思路
没有花里胡哨的操作,直接深度穷举全部出来,不过效率不高做了一些重复工作。
2.代码
第一版未优化代码
class Solution {
public:
vector<string> ans;
//leftk代表目前左括号能剩余的数量
//rightk代表目前右括号还剩余的数量
//totalk代表当前左右括号还剩余的数量
void fun(int leftk,int rightk,int totalk,string tempans){
//totalk为0说明已经搜索到一种组合
if(totalk==0)ans.push_back(tempans);
else{
//当左括号已经添加的数量比右括号数量多的时候才可以加左括号和右括号
//也即是左括号剩余的少,右括号剩余的多
if(leftk<=rightk){
//左括号没用完,可以加左括号也可以加右括号
if(leftk!=0){
//加左括号
fun(leftk-1,rightk,totalk-1,tempans+("("));
//加右括号
fun(leftk,rightk-1,totalk-1,tempans+(")"));
}
//左括号加完了,只剩由括号,直接将右括号全加上去
else{
for(int i=0;i<rightk;i++){
tempans.append(")");
}
//左括号加完右括号也加完,说明搜索到一种答案
ans.push_back(tempans);
}
}
}
}
vector<string> generateParenthesis(int n) {
fun(n,n,2*n,"");
return ans;
}
};
3.优化
在执行过程中会左重复工作
可以使用备忘录优化
当成对的括号匹配成功后,剩余的括号可以不用再搜索了。
class Solution {
public:
vector<string> ans[9];
void fun(int i,int leftk,int rightk,int totalk,string tempans){
//leftk=rightk说明已经目前的括号字符串tempans全是成对的括号,
//剩下的leftk个成对的括号之前已经得到了可以直接使用
if(leftk==rightk&&leftk!=i){
int x=leftk;
int len=ans[x].size();
for(int v=0;v<len;v++){
ans[i].push_back(tempans+ans[x][v]);
}
return;
}else{
if(totalk==0){
ans[i].push_back(tempans);
}
else{
if(leftk<=rightk){
if(leftk!=0){
//加左括号
fun(i,leftk-1,rightk,totalk-1,tempans+("("));
//加右括号
fun(i,leftk,rightk-1,totalk-1,tempans+(")"));
}else{
for(int i=0;i<rightk;i++){
tempans.append(")");
}
ans[i].push_back(tempans);
}
}
}
}
}
vector<string> generateParenthesis(int n) {
ans[0].push_back("");
ans[1].push_back("()");
if(n==1)return ans[n];
for(int i=2;i<=n;i++){
fun(i,i,i,2*i,"");
}
return ans[n];
}
};
即使优化其基本思想依旧是暴力搜索。
可以换一种思路:n个括号组成的字符串中,我们总是拿出最左边的: “(” ,找到其对应的: “)” 。
那么剩下的n-1个括号在哪?
答案是只能在这个括号的里面和右边,因为我们找到的这个括号是最左的
即:( j对括号 )n-1-j对括号
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> ans[n+1];
ans[0].push_back("");
ans[1].push_back("()");
if(n==1)return ans[n];
//计算i对括号的情况
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++){
//括号里面
for(string str1 : ans[j]){
//括号右边
for(string str2 : ans[i-j-1]){
ans[i].push_back("("+str1+")"+str2);
}
}
}
}
return ans[n];
}
};