数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1: 输入:n = 3 输出:[“((()))”,”(()())”,”(())()”,”()(())”,”()()()”]
示例 2: 输入:n = 1 输出:[“()”]
提示:
解题思路 因为之前有做过一题判断括号合法性的题目,所以一开始的想法是,我生成所有可能性的组合,然后判断这些组合中合法的放入结果数组中即可,那么这个题目就转为如何生成所有对应数量括号的组合和检查这些组合是否合法。
那么如何生成全部对应数量括号的组合呢?
n = 0, result = [] n = 1, result = ['(', ')'] n = 2, result = ['((', '()', ')(', '))'] n = 3, result = ['(((', '(()', '()(', '())', ')((', ')()', '))(', ')))'] ... 可以看出一个规律,n+1的组合就是在n组合的基础上后面加上一个'('或者')'
代码可以写为:
let n = 3 let result = []function generateAll (current ) { if (current.length === 2 * n) { result.push (current.join ("" )) }else { current.push ('(' ) generateAll (current) current.pop () current.push (')' ) generateAll (current) current.pop () } } generateAll ([])
如何检查生成的组合是否合法
将左括号视为1,右括号视为-1,按照组合内字符的顺序进行加减,如果过程中出现值小于0,那么说明在没有与之匹配的左括号的情况下添加了右括号,视为不合法。遍历完发现如果值不等于0,说明左括号和右括号的数量不相等,那么也不合法。
代码可以写为:
function valid ( ) { let balance = 0 for (let i = 0 ; i < current.length ; i++) { if (current[i] == '(' ) { ++balance } else { --balance } if (balance < 0 ) { return false } } return balance == 0 }
代码优化 上面两件事分开做,导致了时间消耗变多,可以在生成组合的过程中就进行合法性校验,而不是全部生成完毕之后,根据合法规则去进行过滤。
var generateParenthesis = function (n ) { const ans = [] const current = [] function generate (open ) { if (current.length === n * 2 ) { ans.push (current.join ("" )) return } if (open < n) { current.push ('(' ) generate (open + 1 ) current.pop () } if (current.length - open < open) { current.push (')' ) generate (open) current.pop () } } generate (0 ) return ans };