給定 n 對括號,生成所有合法的括號組合。合法定義:任意前綴中左括號數 ≥ 右括號數,且總數相等。例如 n=3 時輸出:["((()))","(()())","(())()","()(())","()()()"]。
維護兩個計數器:left(已用左括號數)、right(已用右括號數)。每步嘗試:
left < n,可添加 '(',遞歸 (left+1, right)right < left,可添加 ')',遞歸 (left, right+1)left == n && right == n,收集結果關鍵不變量:永不允許 right > left,這自然剪枝了所有非法分支。
public class Solution {
public List generateParenthesis(int n) {
List res = new ArrayList<>();
if (n == 0) return res;
backtrack(res, new StringBuilder(), 0, 0, n);
return res;
}
private void backtrack(List res, StringBuilder cur, int left, int right, int n) {
if (left == n && right == n) {
res.add(cur.toString());
return;
}
if (left < n) {
cur.append('(');
backtrack(res, cur, left + 1, right, n);
cur.deleteCharAt(cur.length() - 1);
}
if (right < left) {
cur.append(')');
backtrack(res, cur, left, right + 1, n);
cur.deleteCharAt(cur.length() - 1);
}
}
}
Cₙ = (2n)!/(n!(n+1)!),每個合法組合生成一次對於回溯算法,建議在 n=2 或 3 時加入打印,觀察遞歸樹的展開順序與回溯點,特別關注 right < left 條件如何精確阻擋非法路徑。