題目:
給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果爲:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
思路:
核心思想是 組合算法的應用。
首先介紹組合算法。從m個元素取n個元素,不考慮取出順序。
一種代碼實現:(基於深度遍歷,此方法爲倒序遍歷)
參考博客:https://blog.csdn.net/weixin_40571331/article/details/82848341
void dfs(int n, int x) {
if (x == r) { //遞歸跳出條件:當數組存儲的數字達到r時輸出
for (int i = 0; i < r; i++)
printf("%d", a[i]);
printf("\n");
}
for (int i = n; i > 0; i--) {
a[x] = i;
dfs(i-1, x+1);
}
}
此問題可簡化爲從2*n個元素中選擇n個元素爲( ,其他元素爲),簡單思考可以得出,第一個元素必爲(,最後一個元素必爲)。即問題變爲從2*n-2個元素中選擇n-1個元素
但並不是每種組合都符合要求,括號匹配時刻必須滿足( 的數量不小於 )的數量。可以在生成字符串時對括號進行計數。
代碼:
class Solution {
static List<String> list = null;
static int len;
public List<String> generateParenthesis(int n) {
list = new ArrayList();
len = n*2-2;
int[] a = new int[n-1];
dfs(n*2-2,0,n-1,a);
return list;
}
public static void dfs(int n, int x,int r,int[] a) {
if (x == r) { //遞歸跳出條件:當數組存儲的數字達到r時輸出
StringBuffer sb = new StringBuffer();
int l=1,m=0;
sb.append('(');
int j=0;
for (int i = 0; i < len; i++){
int t = 0;
if(j<r){
t = len-a[j]+1;
}
if(i+1==t){
l++;
j++;
sb.append("(");
}else{
m++;
sb.append(")");
}
if(l<m) return;
}
sb.append(')');
list.add(sb.toString());
return ;
}
for (int i = n; i > 0; i--) {
a[x] = i;
dfs(i-1, x+1,r,a);
}
}
}
注:leetcode中慎用類變量,上例中arraylist若不每次在generateParenthesis()方法中進行初始化,則會出現上個測試用例的結果仍然在下個測試用例的list中,算是一個小bug吧