题目简述:生成符合条件的括号组合,就是需要括号都要闭合才行
两种解决方案,一种回溯,一种压栈,内部处理逻辑都是一样的
回溯
这是最常见且高效的解法。我们在递归中不断选择添加左括号 ( 或右括号 ),同时用两个变量 left 和 right 分别表示已使用的左右括号数量,递归的过程中做条件剪枝,确保生成的是合法的括号组合。
var generateParenthesis = function (n) {
let res = []
var backtrack = function (left, right, path) {
if (left < right) return
if (path.length === n * 2) {
res.push(path)
return
}
if (left > right) {
backtrack(left, right + 1, path + ')')
}
if (left < n) {
backtrack(left + 1, right, path + '(')
}
}
backtrack(0, 0, '')
return res
};
✅ 思路总结:
- 左括号可以随意加,但总数不能超过
n - 右括号只能在比左括号少时才能加
- 利用递归 + 剪枝避免非法组合
stack
第二种思路与回溯类似,只不过我们使用了一个显式的栈来保存每一步的状态。每次从栈中弹出一个状态,然后扩展它,直到形成合法的组合。
var generateParenthesis = function (n) {
let res = []
let stack = [{
path: '',
left: 0,
right: 0
}]
while (stack.length) {
let item = stack.pop()
let { path, left, right } = item
if (path.length === n * 2) {
res.push(path)
}
if (left > right) {
stack.push({
path: path + ')',
left,
right: right + 1
})
}
if (left < n) {
stack.push({
path: path + '(',
left: left + 1,
right
})
}
}
return res
};
✅ 优点:
- 利用显式栈模拟递归,便于理解每个状态扩展的过程
- 可以视为“非递归”的回溯
很久之后再次写
错误代码
很久没写了,只记得大概的思路,但是错的很彻底
1.首先要return的语句应该放在最上面,所以这里的第四个if,应该挪到最前面
2.然后就是判断括号的情况,因为left>right,这种情况是错误的,其他的情况就都是对的,所以此时应该判断left,right 这两者和 0 的关系,而不是 left 和 right 的关系(因为这里的left以及right都是做的减法,此时需要判断)
var generateParenthesis = function (n) {
let res = [];
var backtrack = function (left, right, path) {
if (left === 0 && right === 0) {
res.push(path);
path = "";
return;
}
if (left < right) {
path += ")";
right--;
}
if (left === right) {
path += "(";
left--;
}
if (left > right) {
return;
}
backtrack(left, right, path);
};
backtrack(n, n, "");
return res;
};
正确代码
var generateParenthesis = function (n) {
let res = [];
var backtrack = function (left, right, path) {
if (left === 0 && right === 0) {
res.push(path);
path = "";
return;
}
if (left > right) {
return;
}
if (left > 0) {
backtrack(left - 1, right, path + "(");
}
if (right > 0) {
backtrack(left, right - 1, path + ")");
}
};
backtrack(n, n, "");
return res;
};