22.括号生成

题目

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

一. 递归法

为了保证括号有效,添加过程中,左括号必须大于等于右括号,所以,递归过程中,如果左括号数等于右括号数,则直接添加左括号,如果左括号数大于右括号数,先复制一个相同的字符串,然后分别添加左括号和右括号。直到左括号数等于目标数,添加剩下的右括号。

js实现

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
  function generate(str, left, right, n, answer) {
    if (left === n) {
      for (var i=0;i<n-right;i++) {
        str += ')'
      }
      answer.push(str)
      return answer
    }
    if (left === right) {
      answer.concat(generate(str + '(', left+1, right, n, answer))
    } else {
      answer.concat(generate(str+'(', left+1, right, n, answer))
      answer.concat(generate(str+')', left, right+1, n, answer))
    }
    return answer
  }

  return generate('', 0, 0, n, [])
}

复杂度分析

时间复杂度:O(4n/sqrt(n))

空间复杂度:O(4n/sqrt(n))

测试结果

✔ Accepted
  ✔ 8/8 cases passed (88 ms)
  ✔ Your runtime beats 40.86 % of javascript submissions
  ✔ Your memory usage beats 5.08 % of javascript submissions (40.9 MB)

二. 闭合数

(来自官方题解)对于每个闭合数 i,我们知道起始和结束括号必定位于索引 0 和 2*i + 1。然后两者间的 2*i 个元素一定是有效序列,其余元素一定是有效序列。

js实现

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
  if (n === 0) {
    return ['']
  }
  var answer = []
  for (var i=0;i<n;i++) {
    generateParenthesis(i).forEach(left => {
      generateParenthesis(n-1-i).forEach(right => {
        answer.push('(' + left + ')' + right)
      })
    })
  }

  return answer
}

复杂度分析

时间复杂度:O(4n/sqrt(n))

空间复杂度:O(4n/sqrt(n))

测试结果

✔ Accepted
  ✔ 8/8 cases passed (80 ms)
  ✔ Your runtime beats 62.34 % of javascript submissions
  ✔ Your memory usage beats 5.08 % of javascript submissions (38.2 MB)

三. 动态规划

当我们知道n-1时的所有可能组合后,我们只需要考虑剩下的一组括号的位置,我们假设左括号始终添加在最左侧,那么右括号可以在剩下的位置之间插入即可,,那我们就可以对所有情况进行遍历:

“(” + 【i=p时所有括号的排列组合】 + “)” + 【i=q时所有括号的排列组合】

其中 p + q = n-1,且 p q 均为非负整数。

p0取到n-1后,所有情况就遍历完了。

js实现

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
  if (n === 0) {
    return ['']
  }

  var answer = [[''], ['()']]

  for (var i=2;i<n+1;i++) {
    var left = []
    for (var j=0;j<i;j++) {
      answer[j].forEach(p => {
        answer[i-1-j].forEach(q => {
          left.push('(' + p + ')' + q)
        })
      })
    }
    answer.push(left)
  }

  return answer[n]
}

测试结果

✔ Accepted
  ✔ 8/8 cases passed (72 ms)
  ✔ Your runtime beats 81.73 % of javascript submissions
  ✔ Your memory usage beats 95.43 % of javascript submissions (34.3 MB)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值