101 lines
2.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @param {number} n
* @return {string[]}
*/
const generateParenthesis = function (n) {
};
/*
这个题目也是一个典型的回溯算法题,一个一个的尝试就行了,问题在于如何检测有效括号,这里可以定义一个栈,这里可以参考
leetcode20题。
思路每一次backtrack从头到尾尝试所有括号尝试所有的排列可能如果长度达到2*n检测是否符合要求如果符合要求
就收集结果,最后返回结果集
*/
function f1(n) {
const result = []; // 结果集
// 初始化括号数组
const brackets = [];
for (let i = 0; i < n; i++) {
brackets.push('(');
brackets.push(')');
}
const bLen = backtrack.length;
// 定义used数组防止重复使用
const used = Array(bLen).fill(false);
const backtrack = (path) => {
// 如果path的长度等于brackets.length,并且有效括号数位n则收集结果
if (path.length === bLen && checkBrackets(path)) {
result.push(path.join(''));
return;
}
for (let i = 0; i < bLen; i++) {
if (used[i]) continue;
path.push(brackets[i]);
used[i] = true;
backtrack(i + 1, path);
path.pop();
used[i] = false;
}
};
backtrack([]);
return Array.from(new Set(result));
}
/*
检测字符串中的括号是否符合要求
*/
function checkBrackets(backets) {
let count = 0;
for (const char of backets) {
if (char === '(') {
count++;
} else if (char === ')') {
count--;
}
// 如果右括号多于左括号,提前返回 false
if (count < 0) return false;
}
// 所有括号遍历完后,必须完全闭合
return count === 0;
}
/*
上面的思路会超时通过全排列去找符合要求的再检测会指数爆炸当n>=5时就已经跑不动了正确的做法应该是
递归的构造符合要求的字符串,当构造的字符串符合要求时,再收集结果。
*/
function f2(n) {
const result = []; // 结果集
/**
*
* @param {String} path 收集的括号组合
* @param {Number} left 左括号的数量
* @param {Number} right 右括号的数量
*/
const backtrack = (path, left, right) => {
// 如果长度达到2*n就收集结果
if (path.length === 2 * n) {
result.push(path);
return;
}
// 如果左括号未达到n就继续构造左括号
if (left < n) {
backtrack(`${path}(`, left + 1, right);
}
// 如果right >= left 再添加右括号会导致,缺少一个左括号和它闭合,所以只有当 right < left 时才添加右括号
if (right < left) {
backtrack(`${path})`, left, right + 1);
}
};
backtrack('', 0, 0);
return result;
}