數字n代表生成括號的對數,請你設計一個函數,用于能夠生成所有可能的并且有效的括號組合。
源代碼:
class Solution {
public:int n;vector<string> ans;string path;vector<string> generateParenthesis(int n) {this->n = n;dfs(0, 0);return ans;}void dfs(int left, int right) {if (path.size() == 2 * n) { // 遞歸出口:已湊夠 2n 個字符ans.push_back(path);return;}if (left < n) { // 可以加 '('path.push_back('(');dfs(left + 1, right);path.pop_back(); // 回溯}if (right < left) { // 可以加 ')'path.push_back(')');dfs(left, right + 1);path.pop_back(); // 回溯}}
};
括號的兩種關系:排列,嵌套;
討論第一個括號:
排列:()…
嵌套:(…)
每種情況進行dfs遞歸;
path設置為string類型,排列的情況只需path = () + path;
嵌套的情況:path = ( + path + );SB
? 嵌套的情況應該是在剩余部分最外側嵌套,這種寫法會導致下次遞歸會在嵌套外側修改。
設置前front,待定path,后back三段;
排列的情況:front = front+();
嵌套的情況:front = front+(; back = )+back;
這樣只能做到在最前面排列單括號,整體嵌套,整體嵌套中最前面排列單括號,在嵌套中排列單括號;
無法再最后面排列單括號,無法在嵌套括號中排列單括號;
希望隨時能直接加()或嵌套;
如果使用了嵌套,則需要在嵌套前,嵌套中,嵌套后的位置同理;
a.嵌套前:
排列:+(); 嵌套:在現在的位置后面+(,在最后+);
b.嵌套中:(前面是本次嵌套的(,后面是本次嵌套的));
排列:+(); 嵌套:在現在的位置后面+(,本次嵌套的)前面+);
c.嵌套后:(前面是上次嵌套的))
排列:+(); 嵌套:在現在的位置后面+(,在最后+);
過于復雜了,這個方法不好。
下面AI給出的實現也報錯了:
class Solution {
public:vector<string> generateParenthesis(int n) {vector<string> ans;dfs("", "", n, n, ans); // prefix, pending, left, rightreturn ans;}private:// 任何時刻真實串 = prefix + pending + 尚未展開的位置void dfs(string prefix, string pending,int left, // 還能再放幾個 '('int right, // 還能再放幾個 ')'vector<string>& ans){// 1. 終止條件:左右括號全都用完if (left == 0 && right == 0) {ans.push_back(prefix + pending); // pending 此時為空return;}// 2. 在當前“可插入點”直接并列一對 ()// 等價于:prefix + pending + "()"// 注意 left、right 各減 1if (left >= 1 && right >= 1) {dfs(prefix + pending + "()", "", left - 1, right - 1, ans);}// 3. 新開一層嵌套:放一個 '(',并把對應的 ')' 壓入 pendingif (left > 0) {dfs(prefix + pending + "(", ")" + pending, left - 1, right, ans);// 注意 pending 被整體右移,相當于把新 ')' 放在本次嵌套的末尾}// 4. 如果還有未匹配的左括號,就把 pending 第一個 ')' 真正落盤if (!pending.empty()) {dfs(prefix + pending[0], pending.substr(1), left, right, ans);// 這里 pending[0] 一定是 ')'}}
};
怎么回退?不回退的話每次遞歸調用都要定義兩個新string。
我是真討厭string。
string類型的數據常用索引處理,而不直接處理字符串本身。
或者直接將選擇過的遍歷作為參數傳遞給遞歸函數:
但是會返回完全一樣的兩組結果,即重復計算了一次。
n=1
排列: front=(); back=nullptr;
嵌套: front=(; back = );
用無序集去重,再轉換成vector:
思路有問題。
無法構造 (())() ;
待定吧,今天懶得想了,再想怕失眠。
無法在最后加()的問題想不到解決的思路。
換思路:感謝靈神
https://leetcode.cn/problems/generate-parentheses/solutions/2071015/hui-su-bu-hui-xie-tao-lu-zai-ci-pythonja-wcdw/?envType=study-plan-v2&envId=top-interview-150
重要條件:當且僅當左括號數量大于右括號數量時,才能加右括號;
有了這個之后直接選與不選 子集法;