括号生成问题,二叉树式回溯 单引号代表一个字符char类型。比如a、(、\n。双引号代表一串字符字符串const char*或string类型。比如abc、(、hello。class Solution { public: vectorstring res; string path; // 用全局/成员变量代替传参 cur void backtrack(int left, int right, int n) { // 终止条件 if (left n right n) { res.push_back(path); return; } // 尝试放左括号 if (left n) { path.push_back((); // ★ 做选择 backtrack(left 1, right, n); path.pop_back(); // ★ 撤销选择回溯 } // 尝试放右括号 if (right left) { path.push_back()); // ★ 做选择 backtrack(left, right 1, n); path.pop_back(); // ★ 撤销选择回溯 } } vectorstring generateParenthesis(int n) { backtrack(0, 0, n); return res; } };代码执行顺序深度优先不是顺序执行cppvoid backtrack(cur, left, right) { if (leftn rightn) 记录; if (left n) backtrack(cur (, left1, right); // ① 先去左 if (right left) backtrack(cur ), left, right1); // ② 等①彻底结束了才来试右 }手动模拟一定要看栈的“返回”过程第 1 步调用backtrack(, 0, 0)。执行if (left n)调用backtrack((, 1, 0)。当前函数暂停去执行左分支第 2 步进入backtrack((, 1, 0)。执行if (left n)调用backtrack(((, 2, 0)。继续往左扎第 3 步进入backtrack(((, 2, 0)。left n不成立2不小于2跳过。执行if (right left)→0 2成立调用backtrack(((), 2, 1)。第 4 步进入backtrack(((), 2, 1)。left n不成立。执行if (right left)→1 2成立调用backtrack((()), 2, 2)。第 5 步进入backtrack((()), 2, 2)。触发终止条件记录(())。返回到第 4 步。回到第 4 步第 4 步的if (right left)执行完了函数结束。返回到第 3 步。回到第 3 步第 3 步的if (right left)执行完了函数结束。返回到第 2 步。回到第 2 步关键转折点第 2 步是backtrack((, 1, 0)。它的第一行if (left n)已经全部执行完毕刚才就是这一步冲进去生了(())。现在程序终于走到下一行代码if (right left)此时right0left1条件成立。调用backtrack((), 1, 1)。第 9 步进入backtrack((), 1, 1)。执行if (left n)调用backtrack(()(, 2, 1)。接着再补右括号得到()()记录。最终结果[(()), ()()]。2. 为什么会产生交错的()()因为回溯return会发生。当你把(())这条直路走到底叶子节点后程序会一层层往回退。当退回到(这个节点时刚才被“搁置”的第二行代码if (right left)终于获得了执行权。它发现此时左括号数1大于右括号数0于是允许放一个右括号这就产生了()进而衍生出()()。