数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1 输出:["()"]
典型的组合问题,用回溯就可以解决。
下面是代码,注释的尽量详细。
回溯从本质上来说就是在选择。
class Solution {
public:
void backtrack(vector<string>&ans,string cur,int left,int right,int n){
//ans是答案字符串数组,即括号组合的组合
//cur是每一个括号组合,取current的前三个字母
//left是当前cur的左括号的数目
//right是当前cur的右括号的数目,分析题目可知右括号数不能大于左括号数
//不然会出现(()))())()之类的非法括号对
//n就是题目给的n,作为递归树的深度
if(cur.size()==n*2){//回溯终点
ans.push_back(cur);//在字符串数组中加入符合条件的括号组合
return;//结束递归
}
if(left<n){//可以加入左括号
cur.push_back('(');//往cur中加入左括号
backtrack(ans,cur,left+1,right,n);//讨论加入了一个左括号后的情况
//这里可以画一个二叉树更好理解,一个分支是加了左括号的,另一个没加
cur.pop_back();//没加左括号的分支
}
if(left>right){//可以加入右括号
cur.push_back(')');//往cur中加入右括号
backtrack(ans,cur,left,right+1,n);//讨论加入了一个右括号后的情况
//同上,这是在讨论右括号的加入情况
cur.pop_back();//没加右括号的分支
}
}
vector<string> generateParenthesis(int n) {//题目给的函数
int left=0,right=0;//起始左右括号数都为0
vector<string> ans;//答案数组,同上
string cur;//答案数组中的元素,即每一个括号组合,同上
backtrack(ans,cur,left,right,n);//回溯
return ans;
}
};