LeetCode22、括号生成

92 阅读1分钟

LeetCode 系列记录我学习算法的过程。

持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 21 天,点击查看活动详情

题目

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:

输入: n = 3
输出: ["((()))","(()())","(())()","()(())","()()()"]

输入: n = 1
输出: ["()"]

提示

  • 1 <= n <= 8

思路

这题可以使用递归的方法,每一位只有两种可能,当左右括号数都用完则将当前分支结果存入结果集里

  • 创建用于存储结果的数组 res
  • 传入 n,代表左右括号数均为 n
  • 创建方法,接受可用左右括号数 leftright,及需要拼接的字符串 str
  • 如果 leftright 均为 0str 则为当前分支结果,存入 res
  • 如果 leftright 相等,则前面的括号已经两相对应,下一位只能拼接 (
  • 反之,下一位可拼接 (),但是要先判断对应括号剩余数是否大于 0
  • 开始调用该方法时,必须传入 (,因为字符串必须以 ( 开头

代码实现

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
    // 存储结果
    const res = []
    
    // 根据传入的字符串拼接上一位 '(' 或 ')'
    function demo(left, right, str) {
        // 如果剩余的左右括号个数为 0,将 str 存入 res
        if (left === 0 && right === 0) return res.push(str)
        // 如果所剩左右括号个数相等 只能拼接 '('
        if (left === right) {
            // 拼接 '(' 的同时左括号剩余个数减 1
            demo(left - 1, right, str + '(')
            
        // 反之则左右括号均可拼接
        } else {
            // 左括号剩余数大于 0,拼接 '('
            left > 0 && demo(left - 1, right, str + '(')
            // 右括号剩余数大于 0,拼接 ')'
            right > 0 && demo(left, right - 1, str + ')')
        }
    }

    // 第一位必须是 ‘(’
    demo(n - 1, n, '(')
    return res
};

image.png

优化

我中间的判断可以略作优化

  • 结束条件仍为左右括号数为 0
  • 当左括号剩余数大于 0,可以添加 (
  • 当右括号剩余数大于左括号,可以添加 )
// 根据传入的字符串拼接上一位 '(' 或 ')'
function demo(left, right, str) {
    // 如果剩余的左右括号个数为 0,将 str 存入 res
    if (left === 0 && right === 0) return res.push(str)
    // 左括号剩余数大于 0,拼接 '('
    if (left > 0) {
        demo(left - 1, right, str + '(')
    }
    // 右括号剩余数大于左括号
    if (right > left) {
        demo(left, right - 1, str + ')')
    }
}