力扣22. 括号生成

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:

输入:n = 3
输出:[
       "((()))",
       "(()())",
       "(())()",
       "()(())",
       "()()()"
     ]

思路:dfs 回溯

1. 产生有效解的情况是left和right均等于n

2. 如果left < right, 说明当前字符串中右括号数多于左括号数,这是不不符合要求的,可以提前终止

3. 如果left < n, 说明还有剩余的左括号没用完,可以继续递归左括号

4. 如果right < n, 说明还有剩余的右括号没用完,还可以继续递归右括号

做加法:

 1 class Solution {
 2     public List<String> generateParenthesis(int n) {
 3         // dfs回溯
 4         List<String> res = new ArrayList<String>();
 5         if(n == 0)
 6             return res;
 7        dfs(res, 0, 0,n, "");
 8        return res;
 9     }
10 
11     public void dfs(List<String> res, int left, int right, int n, String curStr){
12         // 如果left和right都等于n了,说明已经生产了一个解
13         if(left == n && right == n){
14             res.add(curStr);
15             return;
16         }
17         // 剪枝,如果left < right, 说明当前字符串中右括号数多于左括号数,这是不不符合要求的,可以提前终止
18         if(left < right){
19             return;
20         }
21 
22         // 如果左括号数小于n说明还可以继续递归左括号
23         if(left < n){
24             dfs(res, left + 1, right, n, curStr + "(");
25         }
26 
27         // 如果右括号小于n,说明还可以继续递归右括号
28         if(right < n){
29             dfs(res, left, right + 1, n, curStr + ")");
30         }
31     }
32 }    

复杂度分析

上面的程序是对left 和 right 做加法,这里写个做减法的程序:

 1 class Solution {
 2     public List<String> generateParenthesis(int n) {
 3         // dfs回溯
 4 
 5         List<String> res = new ArrayList<String>();
 6         if(n == 0)
 7             return res;
 8        dfs(res, n, n,n, "");
 9        return res;
10     }
11 
12     public void dfs(List<String> res, int left, int right, int n, String curStr){
13         // 如果left和right都等于n了,说明已经生产了一个解
14         if(left == 0 && right == 0){
15             res.add(curStr);
16             return;
17         }
18         // 剪枝,如果left > right, 说明当前字符串中右括号数多于左括号数,这是不不符合要求的,可以提前终止
19         if(left > right){
20             return;
21         }
22 
23         // 如果左括号数大于0,说明还可以继续递归左括号
24         if(left > 0){
25             dfs(res, left - 1, right, n, curStr + "(");
26         }
27 
28         // 如果右括号大于0,说明还可以继续递归右括号
29         if(right > 0){
30             dfs(res, left, right - 1, n, curStr + ")");
31         }
32     }
33 }

使用标准的回溯,

上面两个程序其实是利用了String的不可变性,每个对 curStr 加上左右括号后其实对当前层次的curStr是没有影响的,相当于curStr自动回溯了,这里用StringBuilder代替String,标准的写一遍回溯,加深回溯的印象

 1 class Solution {
 2     public List<String> generateParenthesis(int n) {
 3         // dfs回溯
 4 
 5         List<String> res = new ArrayList<String>();
 6         if(n == 0)
 7             return res;
 8         StringBuilder curStr = new StringBuilder();
 9        dfs(res, n, n,n, curStr);
10        return res;
11     }
12 
13     public void dfs(List<String> res, int left, int right, int n, StringBuilder curStr){
14         // 如果left和right都等于n了,说明已经生产了一个解
15         if(left == 0 && right == 0){
16             res.add(curStr.toString());
17             return;
18         }
19         // 剪枝,如果left > right, 说明当前字符串中右括号数多于左括号数,这是不不符合要求的,可以提前终止
20         if(left > right){
21             return;
22         }
23 
24         // 如果左括号数大于0,说明还可以继续递归左括号
25         if(left > 0){
26             curStr.append("(");
27             dfs(res, left - 1, right, n, curStr);
28             curStr.deleteCharAt(curStr.length() - 1); // 回溯到添加前的转态
29         }
30 
31         // 如果右括号大于0,说明还可以继续递归右括号
32         if(right > 0){
33             curStr.append(")");
34             dfs(res, left, right - 1, n, curStr);
35             curStr.deleteCharAt(curStr.length() - 1);       // 回溯到添加前的转态
36         }
37     }
38 }

思路来源:

https://leetcode-cn.com/problems/generate-parentheses/solution/hui-su-suan-fa-by-liweiwei1419/

猜你喜欢

转载自www.cnblogs.com/hi3254014978/p/12939905.html
今日推荐