-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add JavaScript and TypeScript code of permutations and n_queens (Chap…
…ter of Backtracking) (#494) * Add JavaScript and TypeScript code of permutations and n_queens (Chapter of Backtracking) * Update n_queens.js * Update permutations_i.js * Update permutations_ii.js * Update n_queens.ts * Update permutations_i.ts * Update permutations_ii.ts --------- Co-authored-by: Yudong Jin <krahets@163.com>
- Loading branch information
1 parent
01345c2
commit b52a98f
Showing
6 changed files
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* File: n_queens.js | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:N 皇后 */ | ||
function backtrack(row, n, state, res, cols, diags1, diags2) { | ||
// 当放置完所有行时,记录解 | ||
if (row === n) { | ||
res.push(state.map((row) => row.slice())); | ||
return; | ||
} | ||
// 遍历所有列 | ||
for (let col = 0; col < n; col++) { | ||
// 计算该格子对应的主对角线和副对角线 | ||
const diag1 = row - col + n - 1; | ||
const diag2 = row + col; | ||
// 剪枝:不允许该格子所在 (列 或 主对角线 或 副对角线) 包含皇后 | ||
if (!(cols[col] || diags1[diag1] || diags2[diag2])) { | ||
// 尝试:将皇后放置在该格子 | ||
state[row][col] = 'Q'; | ||
cols[col] = diags1[diag1] = diags2[diag2] = true; | ||
// 放置下一行 | ||
backtrack(row + 1, n, state, res, cols, diags1, diags2); | ||
// 回退:将该格子恢复为空位 | ||
state[row][col] = '#'; | ||
cols[col] = diags1[diag1] = diags2[diag2] = false; | ||
} | ||
} | ||
} | ||
|
||
/* 求解 N 皇后 */ | ||
function nQueens(n) { | ||
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位 | ||
const state = Array.from({ length: n }, () => Array(n).fill('#')); | ||
const cols = Array(n).fill(false); // 记录列是否有皇后 | ||
const diags1 = Array(2 * n - 1).fill(false); // 记录主对角线是否有皇后 | ||
const diags2 = Array(2 * n - 1).fill(false); // 记录副对角线是否有皇后 | ||
const res = []; | ||
|
||
backtrack(0, n, state, res, cols, diags1, diags2); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const n = 4; | ||
const res = nQueens(n); | ||
|
||
console.log(`输入棋盘长宽为 ${n}`); | ||
console.log(`皇后放置方案共有 ${res.length} 种`); | ||
res.forEach((state) => { | ||
console.log('--------------------'); | ||
state.forEach((row) => console.log(row)); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/** | ||
* File: permutations_i.js | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:全排列 I */ | ||
function backtrack(state, choices, selected, res) { | ||
// 当状态长度等于元素数量时,记录解 | ||
if (state.length === choices.length) { | ||
res.push([...state]); | ||
return; | ||
} | ||
// 遍历所有选择 | ||
choices.forEach((choice, i) => { | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if (!selected[i]) { | ||
// 尝试:做出选择,更新状态 | ||
selected[i] = true; | ||
state.push(choice); | ||
// 进行下一轮选择 | ||
backtrack(state, choices, selected, res); | ||
// 回退:撤销选择,恢复到之前的状态 | ||
selected[i] = false; | ||
state.pop(); | ||
} | ||
}); | ||
} | ||
|
||
/* 全排列 I */ | ||
function permutationsI(nums) { | ||
const res = []; | ||
backtrack([], nums, Array(nums.length).fill(false), res); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const nums = [1, 2, 3]; | ||
const res = permutationsI(nums); | ||
|
||
console.log(`输入数组 nums = ${JSON.stringify(nums)}`); | ||
console.log(`所有排列 res = ${JSON.stringify(res)}`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* File: permutations_ii.js | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:全排列 II */ | ||
function backtrack(state, choices, selected, res) { | ||
// 当状态长度等于元素数量时,记录解 | ||
if (state.length === choices.length) { | ||
res.push([...state]); | ||
return; | ||
} | ||
// 遍历所有选择 | ||
const duplicated = new Set(); | ||
choices.forEach((choice, i) => { | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if (!selected[i] && !duplicated.has(choice)) { | ||
// 尝试:做出选择,更新状态 | ||
duplicated.add(choice); // 记录选择过的元素值 | ||
selected[i] = true; | ||
state.push(choice); | ||
// 进行下一轮选择 | ||
backtrack(state, choices, selected, res); | ||
// 回退:撤销选择,恢复到之前的状态 | ||
selected[i] = false; | ||
state.pop(); | ||
} | ||
}); | ||
} | ||
|
||
/* 全排列 II */ | ||
function permutationsII(nums) { | ||
const res = []; | ||
backtrack([], nums, Array(nums.length).fill(false), res); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const nums = [1, 2, 2]; | ||
const res = permutationsII(nums); | ||
|
||
console.log(`输入数组 nums = ${JSON.stringify(nums)}`); | ||
console.log(`所有排列 res = ${JSON.stringify(res)}`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* File: n_queens.ts | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:N 皇后 */ | ||
function backtrack( | ||
row: number, | ||
n: number, | ||
state: string[][], | ||
res: string[][][], | ||
cols: boolean[], | ||
diags1: boolean[], | ||
diags2: boolean[] | ||
): void { | ||
// 当放置完所有行时,记录解 | ||
if (row === n) { | ||
res.push(state.map((row) => row.slice())); | ||
return; | ||
} | ||
// 遍历所有列 | ||
for (let col = 0; col < n; col++) { | ||
// 计算该格子对应的主对角线和副对角线 | ||
const diag1 = row - col + n - 1; | ||
const diag2 = row + col; | ||
// 剪枝:不允许该格子所在 (列 或 主对角线 或 副对角线) 包含皇后 | ||
if (!(cols[col] || diags1[diag1] || diags2[diag2])) { | ||
// 尝试:将皇后放置在该格子 | ||
state[row][col] = 'Q'; | ||
cols[col] = diags1[diag1] = diags2[diag2] = true; | ||
// 放置下一行 | ||
backtrack(row + 1, n, state, res, cols, diags1, diags2); | ||
// 回退:将该格子恢复为空位 | ||
state[row][col] = '#'; | ||
cols[col] = diags1[diag1] = diags2[diag2] = false; | ||
} | ||
} | ||
} | ||
|
||
/* 求解 N 皇后 */ | ||
function nQueens(n: number): string[][][] { | ||
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位 | ||
const state = Array.from({ length: n }, () => Array(n).fill('#')); | ||
const cols = Array(n).fill(false); // 记录列是否有皇后 | ||
const diags1 = Array(2 * n - 1).fill(false); // 记录主对角线是否有皇后 | ||
const diags2 = Array(2 * n - 1).fill(false); // 记录副对角线是否有皇后 | ||
const res: string[][][] = []; | ||
|
||
backtrack(0, n, state, res, cols, diags1, diags2); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const n = 4; | ||
const res = nQueens(n); | ||
|
||
console.log(`输入棋盘长宽为 ${n}`); | ||
console.log(`皇后放置方案共有 ${res.length} 种`); | ||
res.forEach((state) => { | ||
console.log('--------------------'); | ||
state.forEach((row) => console.log(row)); | ||
}); | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* File: permutations_i.ts | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:全排列 I */ | ||
function backtrack( | ||
state: number[], | ||
choices: number[], | ||
selected: boolean[], | ||
res: number[][] | ||
): void { | ||
// 当状态长度等于元素数量时,记录解 | ||
if (state.length === choices.length) { | ||
res.push([...state]); | ||
return; | ||
} | ||
// 遍历所有选择 | ||
choices.forEach((choice, i) => { | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if (!selected[i]) { | ||
// 尝试:做出选择,更新状态 | ||
selected[i] = true; | ||
state.push(choice); | ||
// 进行下一轮选择 | ||
backtrack(state, choices, selected, res); | ||
// 回退:撤销选择,恢复到之前的状态 | ||
selected[i] = false; | ||
state.pop(); | ||
} | ||
}); | ||
} | ||
|
||
/* 全排列 I */ | ||
function permutationsI(nums: number[]): number[][] { | ||
const res: number[][] = []; | ||
backtrack([], nums, Array(nums.length).fill(false), res); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const nums: number[] = [1, 2, 3]; | ||
const res: number[][] = permutationsI(nums); | ||
|
||
console.log(`输入数组 nums = ${JSON.stringify(nums)}`); | ||
console.log(`所有排列 res = ${JSON.stringify(res)}`); | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* File: permutations_ii.ts | ||
* Created Time: 2023-05-13 | ||
* Author: Justin (xiefahit@gmail.com) | ||
*/ | ||
|
||
/* 回溯算法:全排列 II */ | ||
function backtrack( | ||
state: number[], | ||
choices: number[], | ||
selected: boolean[], | ||
res: number[][] | ||
): void { | ||
// 当状态长度等于元素数量时,记录解 | ||
if (state.length === choices.length) { | ||
res.push([...state]); | ||
return; | ||
} | ||
// 遍历所有选择 | ||
const duplicated = new Set(); | ||
choices.forEach((choice, i) => { | ||
// 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 | ||
if (!selected[i] && !duplicated.has(choice)) { | ||
// 尝试:做出选择,更新状态 | ||
duplicated.add(choice); // 记录选择过的元素值 | ||
selected[i] = true; | ||
state.push(choice); | ||
// 进行下一轮选择 | ||
backtrack(state, choices, selected, res); | ||
// 回退:撤销选择,恢复到之前的状态 | ||
selected[i] = false; | ||
state.pop(); | ||
} | ||
}); | ||
} | ||
|
||
/* 全排列 II */ | ||
function permutationsII(nums: number[]): number[][] { | ||
const res: number[][] = []; | ||
backtrack([], nums, Array(nums.length).fill(false), res); | ||
return res; | ||
} | ||
|
||
// Driver Code | ||
const nums: number[] = [1, 2, 2]; | ||
const res: number[][] = permutationsII(nums); | ||
|
||
console.log(`输入数组 nums = ${JSON.stringify(nums)}`); | ||
console.log(`所有排列 res = ${JSON.stringify(res)}`); | ||
|
||
export {}; |