Medium!
題目描述:
給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果為:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
解題思路:
這道題給定一個數字n,讓生成共有n個括號的所有正確的形式,對於這種列出所有結果的題首先還是考慮用遞歸Recursion來解。
由於字符串只有左括號和右括號兩種字符,而且最終結果必定是左括號3個,右括號3個,所以我們定義兩個變量left和right分別表示剩余左右括號的個數。
如果在某次遞歸時,左括號的個數大於右括號的個數,說明此時生成的字符串中右括號的個數大於左括號的個數,即會出現')('這樣的非法串,所以這種情況直接返回,不繼續處理。
如果left和right都為0,則說明此時生成的字符串已有3個左括號和3個右括號,且字符串合法,則存入結果中后返回。
如果以上兩種情況都不滿足,若此時left大於0,則調用遞歸函數,注意參數的更新,若right大於0,則調用遞歸函數,同樣要更新參數。代碼如下:
C++解法一:
1 class Solution { 2 public: 3 vector<string> generateParenthesis(int n) { 4 vector<string> res; 5 generateParenthesisDFS(n, n, "", res); 6 return res; 7 } 8 void generateParenthesisDFS(int left, int right, string out, vector<string> &res) { 9 if (left > right) return; 10 if (left == 0 && right == 0) res.push_back(out); 11 else { 12 if (left > 0) generateParenthesisDFS(left - 1, right, out + '(', res); 13 if (right > 0) generateParenthesisDFS(left, right - 1, out + ')', res); 14 } 15 } 16 };
再來看一種方法,這種方法是CareerCup書上給的方法,感覺也是蠻巧妙的一種方法,該方法的思想是找左括號,每找到一個左括號,就在其后面加一個完整的括號,最后再在開頭加一個(),就形成了所有的情況,需要注意的是,有時候會出現重復的情況,所以我們用set數據結構,好處是如果遇到重復項,不會加入到結果中,最后我們再把set轉為vector即可。
n=1: ()
n=2: (()) ()()
n=3: (()()) ((())) ()(()) (())() ()()()
C++解法二:
1 class Solution { 2 public: 3 vector<string> generateParenthesis(int n) { 4 set<string> t; 5 if (n == 0) t.insert(""); 6 else { 7 vector<string> pre = generateParenthesis(n - 1); 8 for (auto a : pre) { 9 for (int i = 0; i < a.size(); ++i) { 10 if (a[i] == '(') { 11 a.insert(a.begin() + i + 1, '('); 12 a.insert(a.begin() + i + 2, ')'); 13 t.insert(a); 14 a.erase(a.begin() + i + 1, a.begin() + i + 3); 15 } 16 } 17 t.insert("()" + a); 18 } 19 } 20 return vector<string>(t.begin(), t.end()); 21 } 22 };