xxleyi / loop_invariants

记录以及整理「循环不变式」视角下的算法题解

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

leetcode 22. 括号生成

xxleyi opened this issue · comments

题:

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/generate-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


解:

此题是「判断括号有效」和「回溯」的结合。

实质就是比较聪明的穷举。在穷举过程中,我们记录未匹配 ( 的数量 size。当这个数量为 0 时,我们只有一个选择 (。当这个数量大于 0 时,我们有两个选择 ()

穷举终止条件是,已就位的括号数量达到 2n。穷举结果符合题意的结果是 size0,即 ( 完全匹配。

我们要维护的「循环不变式」相关的变量为 size。不变式对任意 i, size >= 0 始终成立。

这里 size 的本质是一个不能为空的栈。

var generateParenthesis = function(n) {
  let res = []
  let parenthesis = Array(n * 2)

  function backtrack(i = 0, size = 0) {
    // termination: push valid parenthesis and return anyway
    if (i == n * 2) {
      if (size == 0) res.push(parenthesis.join(""))
      return
    }

    // we can always add one '('
    parenthesis[i] = '('
    backtrack(i + 1, size + 1)

    // and if size > 0, we can add one ')'
    if (size > 0) {
      parenthesis[i] = ')'
      backtrack(i + 1, size - 1)
    }

    // back at end, we don't need do anything to restore about this special problem
  }

  backtrack()
  return res
};