mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2025-07-28 12:43:12 +08:00
misc: restructure contents
This commit is contained in:
18
experimental/utilities/javascript/binToInt.js
Normal file
18
experimental/utilities/javascript/binToInt.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Does not handle negative binary numbers.
|
||||
function binToInt(binary) {
|
||||
let res = 0;
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
res = res * 2 + +binary[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
console.log(binToInt('0') === parseInt('0', 2) && parseInt('0', 2) === 0);
|
||||
console.log(binToInt('1') === parseInt('1', 2) && parseInt('1', 2) === 1);
|
||||
console.log(binToInt('10') === parseInt('10', 2) && parseInt('10', 2) === 2);
|
||||
console.log(binToInt('11') === parseInt('11', 2) && parseInt('11', 2) === 3);
|
||||
console.log(binToInt('101') === parseInt('101', 2) && parseInt('101', 2) === 5);
|
||||
console.log(
|
||||
binToInt('1100011') === parseInt('1100011', 2) &&
|
||||
parseInt('1100011', 2) === 99,
|
||||
);
|
26
experimental/utilities/javascript/binarySearch.js
Normal file
26
experimental/utilities/javascript/binarySearch.js
Normal file
@ -0,0 +1,26 @@
|
||||
function binarySearch(arr, target) {
|
||||
let left = 0;
|
||||
let right = arr.length - 1;
|
||||
while (left <= right) {
|
||||
const mid = left + Math.floor((right - left) / 2);
|
||||
if (arr[mid] === target) {
|
||||
return mid;
|
||||
}
|
||||
if (arr[mid] < target) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
console.log(binarySearch([1, 2, 3, 10], 1) === 0);
|
||||
console.log(binarySearch([1, 2, 3, 10], 2) === 1);
|
||||
console.log(binarySearch([1, 2, 3, 10], 3) === 2);
|
||||
console.log(binarySearch([1, 2, 3, 10], 10) === 3);
|
||||
console.log(binarySearch([1, 2, 3, 10], 9) === -1);
|
||||
console.log(binarySearch([1, 2, 3, 10], 4) === -1);
|
||||
console.log(binarySearch([1, 2, 3, 10], 0) === -1);
|
||||
console.log(binarySearch([1, 2, 3, 10], 11) === -1);
|
||||
console.log(binarySearch([5, 7, 8, 10], 3) === -1);
|
43
experimental/utilities/javascript/deepEqual.js
Normal file
43
experimental/utilities/javascript/deepEqual.js
Normal file
@ -0,0 +1,43 @@
|
||||
function deepEqual(val1, val2) {
|
||||
if (typeof val1 !== typeof val2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Array comparison.
|
||||
if (Array.isArray(val1) && Array.isArray(val2)) {
|
||||
if (val1.length !== val2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < val1.length; i++) {
|
||||
if (!deepEqual(val1[i], val2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object comparison.
|
||||
if (
|
||||
typeof val1 === 'object' &&
|
||||
typeof val2 === 'object' &&
|
||||
val1 !== null &&
|
||||
val2 !== null
|
||||
) {
|
||||
const keys1 = Object.keys(val1),
|
||||
keys2 = Object.keys(val2);
|
||||
if (keys1.length !== keys2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < keys1.length; i++) {
|
||||
if (!deepEqual(val1[keys1[i]], val2[keys2[i]])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Primitive comparison.
|
||||
return val1 === val2;
|
||||
}
|
||||
|
||||
module.exports = deepEqual;
|
35
experimental/utilities/javascript/graphTopoSort.js
Normal file
35
experimental/utilities/javascript/graphTopoSort.js
Normal file
@ -0,0 +1,35 @@
|
||||
function graphTopoSort(numberNodes, edges) {
|
||||
const nodes = new Map();
|
||||
const order = [];
|
||||
const queue = [];
|
||||
for (let i = 0; i < numberNodes; i++) {
|
||||
nodes.set(i, {in: 0, out: new Set()});
|
||||
}
|
||||
|
||||
edges.forEach(edge => {
|
||||
const [node_id, pre_id] = edge;
|
||||
nodes.get(node_id).in += 1;
|
||||
nodes.get(pre_id).out.add(node_id);
|
||||
});
|
||||
|
||||
for (let [node_id, value] of nodes.entries()) {
|
||||
if (value.in === 0) {
|
||||
queue.push(node_id);
|
||||
}
|
||||
}
|
||||
|
||||
while (queue.length) {
|
||||
const node_id = queue.shift();
|
||||
for (let outgoing_id of nodes.get(node_id).out) {
|
||||
nodes.get(outgoing_id).in -= 1;
|
||||
if (nodes.get(outgoing_id).in === 0) {
|
||||
queue.push(outgoing_id);
|
||||
}
|
||||
}
|
||||
order.push(node_id);
|
||||
}
|
||||
|
||||
return order.length == numberNodes ? order : [];
|
||||
}
|
||||
|
||||
console.log(graphTopoSort(3, [[0, 1], [0, 2]]));
|
21
experimental/utilities/javascript/intToBin.js
Normal file
21
experimental/utilities/javascript/intToBin.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Does not handle negative numbers.
|
||||
function intToBin(number) {
|
||||
if (number === 0) {
|
||||
return '0';
|
||||
}
|
||||
let res = '';
|
||||
while (number > 0) {
|
||||
res = String(number % 2) + res;
|
||||
number = parseInt(number / 2, 10);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
console.log(intToBin(0) === (0).toString(2) && (0).toString(2) === '0');
|
||||
console.log(intToBin(1) === (1).toString(2) && (1).toString(2) === '1');
|
||||
console.log(intToBin(2) === (2).toString(2) && (2).toString(2) === '10');
|
||||
console.log(intToBin(3) === (3).toString(2) && (3).toString(2) === '11');
|
||||
console.log(intToBin(5) === (5).toString(2) && (5).toString(2) === '101');
|
||||
console.log(
|
||||
intToBin(99) === (99).toString(2) && (99).toString(2) === '1100011',
|
||||
);
|
17
experimental/utilities/javascript/intervalsIntersect.js
Normal file
17
experimental/utilities/javascript/intervalsIntersect.js
Normal file
@ -0,0 +1,17 @@
|
||||
// Interval: [start, end].
|
||||
function intervalsIntersect(a, b) {
|
||||
return a[0] < b[1] && b[0] < a[1];
|
||||
}
|
||||
|
||||
console.log(intervalsIntersect([1, 2], [3, 4]) === false);
|
||||
console.log(intervalsIntersect([1, 2], [2, 4]) === false);
|
||||
console.log(intervalsIntersect([1, 2], [1, 4]) === true);
|
||||
console.log(intervalsIntersect([1, 2], [0, 4]) === true);
|
||||
console.log(intervalsIntersect([1, 2], [0, 2]) === true);
|
||||
console.log(intervalsIntersect([1, 2], [0, 1.5]) === true);
|
||||
console.log(intervalsIntersect([3, 4], [1, 2]) === false);
|
||||
console.log(intervalsIntersect([2, 4], [1, 2]) === false);
|
||||
console.log(intervalsIntersect([1, 4], [1, 2]) === true);
|
||||
console.log(intervalsIntersect([0, 4], [1, 2]) === true);
|
||||
console.log(intervalsIntersect([0, 2], [1, 2]) === true);
|
||||
console.log(intervalsIntersect([0, 1.5], [1, 2]) === true);
|
16
experimental/utilities/javascript/intervalsMerge.js
Normal file
16
experimental/utilities/javascript/intervalsMerge.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Interval: [start, end].
|
||||
// Merges two overlapping intervals into one.
|
||||
function intervalsMerge(a, b) {
|
||||
return [Math.min(a[0], b[0]), Math.max(a[1], b[1])];
|
||||
}
|
||||
|
||||
const deepEqual = require('./deepEqual');
|
||||
|
||||
console.log(deepEqual(intervalsMerge([1, 2], [1, 4]), [1, 4]));
|
||||
console.log(deepEqual(intervalsMerge([1, 2], [0, 4]), [0, 4]));
|
||||
console.log(deepEqual(intervalsMerge([1, 2], [0, 2]), [0, 2]));
|
||||
console.log(deepEqual(intervalsMerge([1, 2], [0, 1.5]), [0, 2]));
|
||||
console.log(deepEqual(intervalsMerge([1, 4], [1, 2]), [1, 4]));
|
||||
console.log(deepEqual(intervalsMerge([0, 4], [1, 2]), [0, 4]));
|
||||
console.log(deepEqual(intervalsMerge([0, 2], [1, 2]), [0, 2]));
|
||||
console.log(deepEqual(intervalsMerge([0, 1.5], [1, 2]), [0, 2]));
|
19
experimental/utilities/javascript/isSubsequence.js
Normal file
19
experimental/utilities/javascript/isSubsequence.js
Normal file
@ -0,0 +1,19 @@
|
||||
function isSubsequence(s, t) {
|
||||
if (s.length > t.length) {
|
||||
return false;
|
||||
}
|
||||
let matchedLength = 0;
|
||||
for (let i = 0; i < t.length; i++) {
|
||||
if (matchedLength < s.length && s[matchedLength] === t[i]) {
|
||||
matchedLength += 1;
|
||||
}
|
||||
}
|
||||
return matchedLength === s.length;
|
||||
}
|
||||
|
||||
console.log(isSubsequence('abc', 'abcde') === true);
|
||||
console.log(isSubsequence('abd', 'abcde') === true);
|
||||
console.log(isSubsequence('abf', 'abcde') === false);
|
||||
console.log(isSubsequence('abef', 'abcde') === false);
|
||||
console.log(isSubsequence('abcdef', 'abcde') === false);
|
||||
console.log(isSubsequence('a', 'abcde') === true);
|
22
experimental/utilities/javascript/matrixClone.js
Normal file
22
experimental/utilities/javascript/matrixClone.js
Normal file
@ -0,0 +1,22 @@
|
||||
function matrixClone(matrix, defaultValue) {
|
||||
return matrix.map(row => {
|
||||
return defaultValue === undefined
|
||||
? row.slice(0)
|
||||
: Array(row.length).fill(defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
const deepEqual = require('./deepEqual');
|
||||
|
||||
// Test clone.
|
||||
const a = [[1, 2], [1, 4]];
|
||||
console.log(deepEqual(matrixClone(a), [[1, 2], [1, 4]]));
|
||||
a[0][0] = 4;
|
||||
console.log(deepEqual(matrixClone(a), [[1, 2], [1, 4]]) === false);
|
||||
console.log(deepEqual(matrixClone([[1]]), [[1]]));
|
||||
|
||||
// Test clone with default value.
|
||||
console.log(deepEqual(matrixClone([[1, 2], [1, 4]], 1), [[1, 1], [1, 1]]));
|
||||
console.log(
|
||||
deepEqual(matrixClone([[1, 2], [1, 4]], null), [[null, null], [null, null]]),
|
||||
);
|
12
experimental/utilities/javascript/matrixTranspose.js
Normal file
12
experimental/utilities/javascript/matrixTranspose.js
Normal file
@ -0,0 +1,12 @@
|
||||
function matrixTranspose(matrix) {
|
||||
return matrix[0].map((col, i) => matrix.map(row => row[i]));
|
||||
}
|
||||
|
||||
const deepEqual = require('./deepEqual');
|
||||
|
||||
console.log(deepEqual(matrixTranspose([[1]]), [[1]]));
|
||||
console.log(deepEqual(matrixTranspose([[1, 2]]), [[1], [2]]));
|
||||
console.log(deepEqual(matrixTranspose([[1, 2], [1, 4]]), [[1, 1], [2, 4]]));
|
||||
console.log(
|
||||
deepEqual(matrixTranspose([[1, 2, 3], [4, 5, 6]]), [[1, 4], [2, 5], [3, 6]]),
|
||||
);
|
30
experimental/utilities/javascript/matrixTraverse.js
Normal file
30
experimental/utilities/javascript/matrixTraverse.js
Normal file
@ -0,0 +1,30 @@
|
||||
function traverse(matrix) {
|
||||
const DIRECTIONS = [[0, 1], [0, -1], [1, 0], [-1, 0]];
|
||||
const rows = matrix.length;
|
||||
const cols = matrix[0].length;
|
||||
const visited = matrix.map(row => Array(row.length).fill(false));
|
||||
function dfs(i, j) {
|
||||
if (visited[i][j]) {
|
||||
return;
|
||||
}
|
||||
visited[i][j] = true;
|
||||
DIRECTIONS.forEach(dir => {
|
||||
const row = i + dir[0],
|
||||
col = j + dir[1];
|
||||
// Boundary check.
|
||||
if (row < 0 || row >= rows || col < 0 || col >= cols) {
|
||||
return;
|
||||
}
|
||||
// Valid neighbor check.
|
||||
if (matrix[row][col] !== 1) {
|
||||
return;
|
||||
}
|
||||
dfs(row, col);
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < rows; i++) {
|
||||
for (let j = 0; j < cols; j++) {
|
||||
dfs(i, j);
|
||||
}
|
||||
}
|
||||
}
|
62
experimental/utilities/javascript/mergeSort.js
Normal file
62
experimental/utilities/javascript/mergeSort.js
Normal file
@ -0,0 +1,62 @@
|
||||
function mergeSort(arr) {
|
||||
if (arr.length < 2) {
|
||||
// Arrays of length 0 or 1 are sorted by definition.
|
||||
return arr;
|
||||
}
|
||||
|
||||
const left = arr.slice(0, Math.floor(arr.length / 2));
|
||||
const right = arr.slice(Math.floor(arr.length / 2), Math.floor(arr.length));
|
||||
|
||||
return merge(mergeSort(left), mergeSort(right));
|
||||
}
|
||||
|
||||
function merge(arr1, arr2) {
|
||||
const merged = [];
|
||||
let i = 0,
|
||||
j = 0;
|
||||
|
||||
while (i < arr1.length && j < arr2.length) {
|
||||
if (arr1[i] <= arr2[j]) {
|
||||
merged.push(arr1[i]);
|
||||
i++;
|
||||
} else if (arr2[j] < arr1[i]) {
|
||||
merged.push(arr2[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
merged.push(...arr1.slice(i), ...arr2.slice(j));
|
||||
return merged;
|
||||
}
|
||||
|
||||
const deepEqual = require('./deepEqual');
|
||||
|
||||
console.log(deepEqual(mergeSort([]), []));
|
||||
console.log(deepEqual(mergeSort([1]), [1]));
|
||||
console.log(deepEqual(mergeSort([2, 1]), [1, 2]));
|
||||
console.log(deepEqual(mergeSort([7, 2, 4, 3, 1, 2]), [1, 2, 2, 3, 4, 7]));
|
||||
console.log(deepEqual(mergeSort([1, 2, 3, 4, 5, 0]), [0, 1, 2, 3, 4, 5]));
|
||||
console.log(
|
||||
deepEqual(mergeSort([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
]),
|
||||
);
|
||||
console.log(
|
||||
deepEqual(mergeSort([98322, 3242, 876, -234, 34, 12331]), [
|
||||
-234,
|
||||
34,
|
||||
876,
|
||||
3242,
|
||||
12331,
|
||||
98322,
|
||||
]),
|
||||
);
|
13
experimental/utilities/javascript/treeEqual.js
Normal file
13
experimental/utilities/javascript/treeEqual.js
Normal file
@ -0,0 +1,13 @@
|
||||
function treeEqual(node1, node2) {
|
||||
if (!node1 && !node2) {
|
||||
return true;
|
||||
}
|
||||
if (!node1 || !node2) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
node1.val == node2.val &&
|
||||
treeEqual(node1.left, node2.left) &&
|
||||
treeEqual(node1.right, node2.right)
|
||||
);
|
||||
}
|
10
experimental/utilities/javascript/treeMirror.js
Normal file
10
experimental/utilities/javascript/treeMirror.js
Normal file
@ -0,0 +1,10 @@
|
||||
function treeMirror(node) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
let temp = node.left;
|
||||
node.left = node.right;
|
||||
node.right = temp;
|
||||
treeMirror(node.left);
|
||||
treeMirror(node.right);
|
||||
}
|
Reference in New Issue
Block a user