一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
BFS
-
n=1时,组合情况仅一种:["()"]
-
n=2时
- 遍历 n=1 的组合情况 ["()"]
- 对于情况 "()",在该字符串每个位置填入一对括号 () 后得到:["()()","(())","()()"]
- 去重得到最终组合情况为:["()()","(())"]
-
n=3时
- 遍历 n=2 的组合情况 ["()()","(())"]
- 对于情况 "()()",在每个位置填入一对括号 () 后得到:["()()()","(())()","()()()","()(())","()()()"]
- 对于情况 "(())",在每个位置填入一对括号 () 后得到:["()(())","(()())","((()))","(()())","(())()"]
- 去重得到最终组合情况为:["()()()","(())()","()(())","(()())","((()))"]
var generateParenthesis = function (n) {
let set = new Set(['()']);
for (let c = 2; c <= n; c++) {
let nextSet = new Set();
for (const s of set) {
for (let j = 0; j <= s.length; j++) {
nextSet.add(s.slice(0, j) + '()' + s.slice(j));
}
}
set = nextSet;
}
return [...set];
};
递归
1.大致思路就是不停选括号,要么选左括号,要么选右括号,所以可以用dfs来实现 2.利用约束做剪枝,这里有两个约束条件
- 只要左括号有剩,就可以选它,然后继续做选择(递归)
- 右括号比左括号剩的多,才能选右括号,然后继续做选择(递归)
- 当str的长度为 2 * n 时,结束递归
var generateParenthesis = function (n) {
const res = [];
const dfs = (lRemain, rRemain, str) => { // 左右括号所剩的数量,str是当前字符串
if (str.length == 2 * n) { // 字符串构建完成
res.push(str); // 加入解集
return; // 结束当前递归分支
}
if (lRemain > 0) { // 只要左括号有剩,就可以选它,然后继续做选择(递归)
dfs(lRemain - 1, rRemain, str + "(");
}
if (lRemain < rRemain) { // 右括号比左括号剩的多,才能选右括号
dfs(lRemain, rRemain - 1, str + ")"); // 然后继续做选择(递归)
}
};
dfs(n, n, ""); // 递归的入口,剩余数量都是n,初始字符串是空串
return res;
};
/**
* @param {number} n
* @return {string[]}
*/
var generateParenthesis = function (n) {
const res = []
function dfs(l, r, s) {
if (l === 0 && r === 0) {
res.push(s)
return
}
if (l > r) return
if (l > 0) dfs(l - 1, r, s + '(')
if (r > 0) dfs(l, r - 1, s + ')')
}
dfs(n, n, '')
return res
};