方法一:暴力破解
生成所有可能的字符串組合,然後檢查有效的字符串。一共可以生成的字符串個數爲:
爲了生成所有序列,我們使用遞歸。長度爲 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);
}
}