【Leetcode】22.括号生成

85 阅读2分钟

leetcode-22.png

题目简述:生成符合条件的括号组合,就是需要括号都要闭合才行

两种解决方案,一种回溯,一种压栈,内部处理逻辑都是一样的

回溯

这是最常见且高效的解法。我们在递归中不断选择添加左括号 ( 或右括号 ),同时用两个变量 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 的关系,而不是 leftright 的关系(因为这里的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;
};