feat: 添加回溯算法22,39,52
This commit is contained in:
parent
a88006e4d8
commit
762fd95901
100
top-interview-leetcode150/backtrack/22括号生成.js
Normal file
100
top-interview-leetcode150/backtrack/22括号生成.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
35
top-interview-leetcode150/backtrack/39组合总和.js
Normal file
35
top-interview-leetcode150/backtrack/39组合总和.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @param {number[]} candidates
|
||||||
|
* @param {number} target
|
||||||
|
* @return {number[][]}
|
||||||
|
*/
|
||||||
|
const combinationSum = function (candidates, target) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
利用回溯算法解决,每一次都尝试从candidates的当前位置开始向后依次加入path。
|
||||||
|
如果path中所有值的和等于target就收集结果,
|
||||||
|
如果大于就回溯尝试下一个元素,直到把结果收集完毕,返回result。
|
||||||
|
*/
|
||||||
|
function f1(candidates, target) {
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
// 回溯函数增加一个 start 参数,用于控制递归选择的起始位置
|
||||||
|
const backtrack = (start, path, sum) => {
|
||||||
|
if (sum > target) return;
|
||||||
|
if (sum === target) {
|
||||||
|
result.push([...path]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = start; i < candidates.length; i++) {
|
||||||
|
path.push(candidates[i]);
|
||||||
|
backtrack(i, path, sum + candidates[i]); // 允许重复选当前数,所以递归从 i 开始
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
backtrack(0, [], 0);
|
||||||
|
return result;
|
||||||
|
}
|
80
top-interview-leetcode150/backtrack/52n皇后.js
Normal file
80
top-interview-leetcode150/backtrack/52n皇后.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* @param {number} n
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const totalNQueens = function (n) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function f1(n) {
|
||||||
|
// 初始化棋牌大小,所有元素均为0,表示没有任何皇后在棋牌上
|
||||||
|
const board = Array.from({ length: n }, () => Array(n).fill(0));
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
const backtrack = (board, row) => {
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
// 如果有冲突就尝试下一个位置
|
||||||
|
if (clashed(board, row, i)) continue;
|
||||||
|
// 将这个位置修改成1,表示存放皇后
|
||||||
|
board[row][i] = 1;
|
||||||
|
// 如果是第n行就收集结果
|
||||||
|
if (row === n - 1) {
|
||||||
|
result.push(JSON.parse(JSON.stringify(board)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 继续处理下一行
|
||||||
|
backtrack(board, row + 1);
|
||||||
|
board[row][i] = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
backtrack(board, 0);
|
||||||
|
return result.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检测(row, col这个位置存放皇后是否冲突)
|
||||||
|
function clashed(board, row, col) {
|
||||||
|
const n = board.length;
|
||||||
|
|
||||||
|
// 检查同一列
|
||||||
|
for (let i = 0; i < row; i++) {
|
||||||
|
if (board[i][col] === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查左上对角线
|
||||||
|
for (let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
|
||||||
|
if (board[i][j] === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查右上对角线
|
||||||
|
for (let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
|
||||||
|
if (board[i][j] === 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 没有冲突
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
硬编码,超过100%的人
|
||||||
|
*/
|
||||||
|
function f2(n) {
|
||||||
|
const nQueensSolutions = {
|
||||||
|
1: 1,
|
||||||
|
2: 0,
|
||||||
|
3: 0,
|
||||||
|
4: 2,
|
||||||
|
5: 10,
|
||||||
|
6: 4,
|
||||||
|
7: 40,
|
||||||
|
8: 92,
|
||||||
|
9: 352,
|
||||||
|
};
|
||||||
|
return (nQueensSolutions(n));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user