Add JavaScript and TypeScript code of heap sort, selection sort and binary search edge and Fix the indentation of TS code (#545)

* Fix the indentation of TS code

* Add JavaScript and TypeScript code of heap sort, selection sort and binary search edge

* Fix the style of JS and TS code
pull/548/head
Justin Tse 1 year ago committed by GitHub
parent 6377e3316a
commit 2532f06c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,55 @@
/**
* File: binary_search_edge.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 二分查找最左一个元素 */
function binary_search_left_edge(nums, target) {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
if (i == nums.length || nums[i] != target) {
return -1; // 未找到目标元素,返回 -1
}
return i;
}
/* 二分查找最右一个元素 */
function binary_search_right_edge(nums, target) {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
i = m + 1; // 首个大于 target 的元素在区间 [m+1, j] 中
}
}
if (j == nums.length || nums[j] != target) {
return -1; // 未找到目标元素,返回 -1
}
return j;
}
/* Driver Code */
let target = 6;
const nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15];
// 二分查找最左一个元素
let index_left = binary_search_left_edge(nums, target);
console.log("数组中最左一个元素 6 的索引 = ", index_left);
// 二分查找最右一个元素
let index_right = binary_search_right_edge(nums, target);
console.log("数组中最右一个元素 6 的索引 = ", index_right);

@ -0,0 +1,49 @@
/**
* File: heap_sort.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
function sift_down(nums, n, i) {
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
let l = 2 * i + 1;
let r = 2 * i + 2;
let ma = i;
if (l < n && nums[l] > nums[ma]) {
ma = l;
}
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma === i) {
break;
}
// 交换两节点
[nums[i], nums[ma]] = [nums[ma], nums[i]];
// 循环向下堆化
i = ma;
}
}
/* 堆排序 */
function heap_sort(nums) {
// 建堆操作:堆化除叶节点以外的其他所有节点
for (let i = Math.floor(nums.length / 2) - 1; i >= 0; i--) {
sift_down(nums, nums.length, i);
}
// 从堆中提取最大元素,循环 n-1 轮
for (let i = nums.length - 1; i > 0; i--) {
// 交换根节点与最右叶节点(即交换首元素与尾元素)
[nums[0], nums[i]] = [nums[i], nums[0]];
// 以根节点为起点,从顶至底进行堆化
sift_down(nums, i, 0);
}
}
/* Driver Code */
const nums = [4, 1, 3, 1, 5, 2];
heap_sort(nums);
console.log("堆排序完成后 nums =", nums);

@ -0,0 +1,27 @@
/**
* File: selection_sort.js
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 选择排序 */
function selection_sort(nums) {
let n = nums.length;
// 外循环:未排序区间为 [i, n-1]
for (let i = 0; i < n - 1; i++) {
// 内循环:找到未排序区间内的最小元素
let k = i;
for (let j = i + 1; j < n; j++) {
if (nums[j] < nums[k]) {
k = j; // 记录最小元素的索引
}
}
// 将该最小元素与未排序区间的首个元素交换
[nums[i], nums[k]] = [nums[k], nums[i]];
}
}
/* Driver Code */
const nums = [4, 1, 3, 1, 5, 2];
selection_sort(nums);
console.log("选择排序完成后 nums =", nums);

@ -16,7 +16,7 @@ function backtrack(
): void {
// 当放置完所有行时,记录解
if (row === n) {
res.push(state.map((row) => row.slice()));
res.push(state.map(row => row.slice()));
return;
}
// 遍历所有列
@ -27,12 +27,12 @@ function backtrack(
// 剪枝:不允许该格子所在 (列 或 主对角线 或 副对角线) 包含皇后
if (!(cols[col] || diags1[diag1] || diags2[diag2])) {
// 尝试:将皇后放置在该格子
state[row][col] = 'Q';
state[row][col] = "Q";
cols[col] = diags1[diag1] = diags2[diag2] = true;
// 放置下一行
backtrack(row + 1, n, state, res, cols, diags1, diags2);
// 回退:将该格子恢复为空位
state[row][col] = '#';
state[row][col] = "#";
cols[col] = diags1[diag1] = diags2[diag2] = false;
}
}
@ -41,7 +41,7 @@ function backtrack(
/* 求解 N 皇后 */
function nQueens(n: number): string[][][] {
// 初始化 n*n 大小的棋盘,其中 'Q' 代表皇后,'#' 代表空位
const state = Array.from({ length: n }, () => Array(n).fill('#'));
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); // 记录副对角线是否有皇后
@ -57,9 +57,7 @@ const res = nQueens(n);
console.log(`输入棋盘长宽为 ${n}`);
console.log(`皇后放置方案共有 ${res.length}`);
res.forEach((state) => {
console.log('--------------------');
state.forEach((row) => console.log(row));
res.forEach(state => {
console.log("--------------------");
state.forEach(row => console.log(row));
});
export {};

@ -0,0 +1,55 @@
/**
* File: binary_search_edge.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 二分查找最左一个元素 */
function binary_search_left_edge(nums: number[], target: number): number {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
j = m - 1; // 首个小于 target 的元素在区间 [i, m-1] 中
}
}
if (i == nums.length || nums[i] != target) {
return -1; // 未找到目标元素,返回 -1
}
return i;
}
/* 二分查找最右一个元素 */
function binary_search_right_edge(nums: number[], target: number): number {
let i = 0, j = nums.length - 1; // 初始化双闭区间 [0, n-1]
while (i <= j) {
let m = Math.floor((i + j) / 2); // 计算中点索引 m
if (nums[m] < target) {
i = m + 1; // target 在区间 [m+1, j] 中
} else if (nums[m] > target) {
j = m - 1; // target 在区间 [i, m-1] 中
} else {
i = m + 1; // 首个大于 target 的元素在区间 [m+1, j] 中
}
}
if (j == nums.length || nums[j] != target) {
return -1; // 未找到目标元素,返回 -1
}
return j;
}
/* Driver Code */
let target: number = 6;
const nums: number[] = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15];
// 二分查找最左一个元素
let index_left: number = binary_search_left_edge(nums, target);
console.log("数组中最左一个元素 6 的索引 = ", index_left);
// 二分查找最右一个元素
let index_right: number = binary_search_right_edge(nums, target);
console.log("数组中最右一个元素 6 的索引 = ", index_right);

@ -0,0 +1,51 @@
/**
* File: heap_sort.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
function sift_down(nums: number[], n: number, i: number): void {
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
let l = 2 * i + 1;
let r = 2 * i + 2;
let ma = i;
if (l < n && nums[l] > nums[ma]) {
ma = l;
}
if (r < n && nums[r] > nums[ma]) {
ma = r;
}
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma === i) {
break;
}
// 交换两节点
[nums[i], nums[ma]] = [nums[ma], nums[i]];
// 循环向下堆化
i = ma;
}
}
/* 堆排序 */
function heap_sort(nums: number[]): void {
// 建堆操作:堆化除叶节点以外的其他所有节点
for (let i = Math.floor(nums.length / 2) - 1; i >= 0; i--) {
sift_down(nums, nums.length, i);
}
// 从堆中提取最大元素,循环 n-1 轮
for (let i = nums.length - 1; i > 0; i--) {
// 交换根节点与最右叶节点(即交换首元素与尾元素)
[nums[0], nums[i]] = [nums[i], nums[0]];
// 以根节点为起点,从顶至底进行堆化
sift_down(nums, i, 0);
}
}
/* Driver Code */
const nums: number[] = [4, 1, 3, 1, 5, 2];
heap_sort(nums);
console.log("堆排序完成后 nums =", nums);
export { };

@ -0,0 +1,29 @@
/**
* File: selection_sort.ts
* Created Time: 2023-06-04
* Author: Justin (xiefahit@gmail.com)
*/
/* 选择排序 */
function selection_sort(nums: number[]): void {
let n = nums.length;
// 外循环:未排序区间为 [i, n-1]
for (let i = 0; i < n - 1; i++) {
// 内循环:找到未排序区间内的最小元素
let k = i;
for (let j = i + 1; j < n; j++) {
if (nums[j] < nums[k]) {
k = j; // 记录最小元素的索引
}
}
// 将该最小元素与未排序区间的首个元素交换
[nums[i], nums[k]] = [nums[k], nums[i]];
}
}
/* Driver Code */
const nums: number[] = [4, 1, 3, 1, 5, 2];
selection_sort(nums);
console.log("选择排序完成后 nums =", nums);
export { };
Loading…
Cancel
Save