22.產生括號組合
22. Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
暴力枚舉
暴力破解的思路也很簡單。而關鍵一點是如何判斷枚舉出來的結果是正確的。這裏使用了平衡值來判斷。通過掃描當前的字符串,左括號使值加一,右括號使值減一。當平衡值爲0的話,那麼就代表着左括號和右括號相等,即滿足題目的條件。否認則丟棄該結果。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> combinations = new ArrayList();
generateAll(new char[2 * n], 0, combinations);
return combinations;
}
public void generateAll(char[] current, int pos, List<String> result) {
if (pos == current.length) {
if (valid(current))
result.add(new String(current));
} else {
current[pos] = '(';
generateAll(current, pos+1, result);
current[pos] = ')';
generateAll(current, pos+1, result);
}
}
public boolean valid(char[] current) {
int balance = 0;
for (char c: current) {
if (c == '(') balance++;
else balance--;
if (balance < 0) return false;
}
return (balance == 0);
}
}
回溯法
這種組合問題是一個枚舉問題。需要枚舉出所有的情況,也正因爲如此,使用回溯法是一種很不錯的方式。回溯法的關鍵就是判斷當前狀態是否滿足所給條件或者是否爲最優狀態。如果不滿足就回到上一步。而本題當中,隱藏的條件就是左括號數量必須與右括號的數量相等。即如果所給結果總長度爲n的話,左右括號的個數必然是n/2。
代碼14行表示,左括號的個數並沒有達到目的個數。而18行表示,右括號的個數並沒有與左括號的個數相等。而第9行表示,已經達到了目的個數,可以返回了。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList();
backtrack(result,"",0,0,n);
return result;
}
public void backtrack(List<String> result,String cur, int open, int close, int max){
if(cur.length() == max * 2){
result.add(cur);
return;
}
if(open < max){
backtrack(result,cur+'(',open+1,close,max);
}
if(close < open){
backtrack(result,cur+')',open,close+1,max);
}
}
}