方法一:暴力破解
生成所有可能的字符串组合,然后检查有效的字符串。一共可以生成的字符串个数为:
为了生成所有序列,我们使用递归。长度为 n
的序列就是 '('
加上所有长度为 n-1
的序列,以及 ')'
加上所有长度为 n-1
的序列。
为了检查序列是否为有效的,我们会跟踪平衡
,也就是左括号的数量减去右括号的数量的净值。如果这个值始终小于零或者不以零结束,该序列就是无效的,否则它是有效的。
package leetcode.problem22;
import java.util.ArrayList;
import java.util.List;
class Solution2 {
public static List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
getAll(new char[2 * n], 0, result);
return result;
}
private static void getAll(char[] chars, int i, List<String> result) {
if (i == chars.length){
if (valid(chars)){
result.add(new String(chars));
}
return;
}else {
chars[i] = '(';
getAll(chars, i + 1, result);
chars[i] = ')';
getAll(chars, i + 1, result);
}
}
private static boolean valid(char[] chars) {
int t = 0;
for (char c : chars){
if (c == '('){
t++;
}else if (c == ')'){
t--;
}
if (t < 0){
return false;
}
}
return t == 0;
}
}
复杂度分析:
时间复杂度:,对于每一个子序列验证其合法性的时间复杂度为
空间复杂度:
方法二:回溯法
先写n个左括号,然后就写右括号,每当完成一组之后,就吧字符串存起来。然后再倒退步骤到写第n-1个左括号,然后写右括号,在写左括号,再全写右括号。依次回溯递归,每完成一趟就回到能再改变的位置。
package leetcode.problem22;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Solution3 {
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
solve(result,"",0,0,n);
return result;
}
private void solve(List<String> result, String s, int start, int end, int n) {
if (s.length() == 2 * n){
result.add(s);
return;
}
if (start < n){
solve(result, s + "(",start + 1,end,n);
}
if (end < start){
solve(result, s + ")",start,end + 1,n);
}
}
}
方法三
先是找左括号,每找到一个左括号,就在其后面加一个完整的括号,最后再在开头加一个(),就形成了所有的情况,需要注意的是,有时候会出现重复的情况,所以用set数据结构,好处是如果遇到重复项,不会加入到结果中,最后再把set转为list即可。
n=1: ()
n=2: (()) ()()
n=3: (()()) ((())) ()(()) (())() ()()()
package leetcode.problem22;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
class Solution {
public List<String> generateParenthesis(int n) {
Set<String> result = new HashSet<>();
if (n == 0){
result.add("");
}else {
List<String> pre = generateParenthesis(n - 1);
for (String string : pre){
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == '('){
result.add(string.substring(0, i + 1) + "()" + string.substring(i + 1 ));
}
}
result.add("()" + string);
}
}
return new ArrayList<>(result);
}
}