- 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
有效括号组合需满足:左括号必须以正确的顺序闭合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
注:
以该图为例子,观察可得:
1.只有当右边括号个数大于或等于左边个数才可以。(right>=left)
2.当left == n&& right ==n 是结束条件,此时将拼接好的字符串string添加进结果列表ans中。
在对于每次的dfs中,模拟对该树的操作。即为:
1.如果left>0,则先将一个左括号加入到string中。然后对其的子树(下一层)进行相同的操作。当左边括号操作完成(left= =0)时,再进入判断操作右括号,如果right>0,则右边括号被添加进入string.
对于dfs,需要找到一个终止条件,然后其进行的操作就是模拟对树的操作。其中操作每一层的节点的时候,他的string,是不会受到子树string的影响。
如图中所示,令string为空字符串的根节点为第0层,则左一右二的节点为第1层,此时第1层的string="(",他将该string传入第2层,而第二层再次进行string+"(",第二层给第三层的string="(("…以此类推。当第二层的dfs进行完毕后,是相当于跳出了第一层的这段代码
if(left > 0){
//左括号数减1,再继续dfs。相当于进入到树的下一层。
dfs(left-1,right,ans,string+"(");
}
所以第一层的string仍然为"(",然后第一次再进入
//如果右括号个数大于0,则先加入右括号
if(right>0){
//右括号数减1,再继续dfs。相当于进入到树的下一层。
dfs(left,right-1,ans,string+")");
}
此时和上面类似。每次进入dfs就是进入了另一个函数,传递的sting参数不同,但不会影响原来函数的string。例如 :a 函数的x=1,传递给b函数的参数为x=x+1,如果打印两个函数中的x,a中为1.b中为2,b不影响a.
class Solution {
public List<String> generateParenthesis(int n) {
List<String> ans = new ArrayList<>();
dfs(n,n,ans,"");
return ans;
}
public static void dfs(int left, int right , List<String> ans,String string) {
//左右括号都用完了,就返回存储当前字符串。
if(left ==0 && right==0){
ans.add(string);
}
//右边括号个数必须大于或者等于左边括号个数,否则不行。
if(right >= left){
//如果左括号个数大于0,则先加入左括号
if(left > 0){
//左括号数减1,再继续dfs。相当于进入到树的下一层。
dfs(left-1,right,ans,string+"(");
}
//System.out.println(left+" "+right+" "+string);
//如果右括号个数大于0,则先加入右括号
if(right>0){
//右括号数减1,再继续dfs。相当于进入到树的下一层。
dfs(left,right-1,ans,string+")");
}
}
}
}