題目描述:
給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果為:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
題目解析:動態規划
首先,面向小白:什么是動態規划?在此題中,動態規划的思想類似於數學歸納法,當知道所有 i<n 的情況時,我們可以通過某種算法算出 i=n 的情況。
本題最核心的思想是,考慮 i=n 時相比 n-1 組括號增加的那一組括號的位置。
思路:
當我們清楚所有 i<n 時括號的可能生成排列后,對與 i=n 的情況,我們考慮整個括號排列中最左邊的括號。
它一定是一個左括號,那么它可以和它對應的右括號組成一組完整的括號 "( )",我們認為這一組是相比 n-1 增加進來的括號。
那么,剩下 n-1 組括號有可能在哪呢?
【這里是重點,請着重理解】
剩下的括號要么在這一組新增的括號內部,要么在這一組新增括號的外部(右側)。
既然知道了 i<n 的情況,那我們就可以對所有情況進行遍歷:
"(" + 【i=p時所有括號的排列組合】 + ")" + 【i=q時所有括號的排列組合】
其中 p + q = n-1,且 p q 均為非負整數。
事實上,當上述 p 從 0 取到 n-1,q 從 n-1 取到 0 后,所有情況就遍歷完了。
注:上述遍歷是沒有重復情況出現的,即當 (p1,q1)≠(p2,q2) 時,按上述方式取的括號組合一定不同。
代碼實現:
LinkedList<LinkedList<String>> result = new LinkedList<>();
if (n == 0) {
return new LinkedList<>();
}
LinkedList<String> list0 = new LinkedList<>();
list0.add("");
result.add(list0);
LinkedList<String> list1 = new LinkedList<>();
//當n=1時,只有一組括號
list1.add("()");
result.add(list1);
for (int i = 2; i <= n; i++) {
LinkedList<String> temp = new LinkedList<>();
for (int j = 0; j < i; j++) {
List<String> str1 = result.get(j);
List<String> str2 = result.get(i - 1 - j);
for (String s1 : str1) {
for (String s2 : str2) {
String el = "(" + s1 + ")" + s2;
temp.add(el);
}
}
}
result.add(temp);
}
return result.get(n);
