From d57b7250348872dae67d476bfbc25fca75bc88ec Mon Sep 17 00:00:00 2001 From: Tien Do Date: Wed, 13 Jun 2018 10:27:02 +0700 Subject: [PATCH 01/44] chore: ignore .DS_Store in git (#65) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 640c06087a..e128b69788 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules .idea coverage .vscode +.DS_Store From c3a961840d82868d51165a6b023b30b66cf46547 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 13 Jun 2018 06:39:18 +0300 Subject: [PATCH 02/44] Fix BST removal method. --- src/data-structures/tree/avl-tree/AvlTree.js | 8 ++++++++ .../tree/avl-tree/__test__/AvlTRee.test.js | 10 ++++++++++ .../tree/binary-search-tree/BinarySearchTree.js | 2 +- .../tree/binary-search-tree/BinarySearchTreeNode.js | 4 ++-- .../__test__/BinarySearchTree.test.js | 8 ++++---- .../__test__/BinarySearchTreeNode.test.js | 8 ++++---- .../tree/red-black-tree/RedBlackTree.js | 2 +- 7 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/data-structures/tree/avl-tree/AvlTree.js b/src/data-structures/tree/avl-tree/AvlTree.js index b4b86ea474..51e6a05f92 100644 --- a/src/data-structures/tree/avl-tree/AvlTree.js +++ b/src/data-structures/tree/avl-tree/AvlTree.js @@ -16,6 +16,14 @@ export default class AvlTree extends BinarySearchTree { } } + /** + * @param {*} value + * @return {boolean} + */ + remove(value) { + throw new Error(`Can't remove ${value}. Remove method is not implemented yet`); + } + /** * @param {BinarySearchTreeNode} node */ diff --git a/src/data-structures/tree/avl-tree/__test__/AvlTRee.test.js b/src/data-structures/tree/avl-tree/__test__/AvlTRee.test.js index 5be7d119e9..fb1f3ee413 100644 --- a/src/data-structures/tree/avl-tree/__test__/AvlTRee.test.js +++ b/src/data-structures/tree/avl-tree/__test__/AvlTRee.test.js @@ -229,4 +229,14 @@ describe('AvlTree', () => { expect(tree.toString()).toBe('10,15,18,30,35,40,42,43,45,47'); expect(tree.root.height).toBe(3); }); + + it('should throw an error when trying to remove the node', () => { + const removeNodeAvlTree = () => { + const tree = new AvlTree(); + + tree.remove(1); + }; + + expect(removeNodeAvlTree).toThrowError(); + }); }); diff --git a/src/data-structures/tree/binary-search-tree/BinarySearchTree.js b/src/data-structures/tree/binary-search-tree/BinarySearchTree.js index e70950f916..b9e2ddad53 100644 --- a/src/data-structures/tree/binary-search-tree/BinarySearchTree.js +++ b/src/data-structures/tree/binary-search-tree/BinarySearchTree.js @@ -29,7 +29,7 @@ export default class BinarySearchTree { /** * @param {*} value - * @return {BinarySearchTreeNode} + * @return {boolean} */ remove(value) { return this.root.remove(value); diff --git a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js index d6fe4bae97..9ad74483da 100644 --- a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js +++ b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js @@ -81,7 +81,7 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { /** * @param {*} value - * @return {BinarySearchTreeNode} + * @return {boolean} */ remove(value) { const nodeToRemove = this.find(value); @@ -120,7 +120,7 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { } } - return nodeToRemove; + return true; } /** diff --git a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js index 593014d80b..981a118d9e 100644 --- a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js +++ b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js @@ -43,13 +43,13 @@ describe('BinarySearchTree', () => { expect(bst.toString()).toBe('5,10,20'); - const removedNode1 = bst.remove(5); + const removed1 = bst.remove(5); expect(bst.toString()).toBe('10,20'); - expect(removedNode1.value).toBe(5); + expect(removed1).toBeTruthy(); - const removedNode2 = bst.remove(20); + const removed2 = bst.remove(20); expect(bst.toString()).toBe('10'); - expect(removedNode2.value).toBe(20); + expect(removed2).toBeTruthy(); }); it('should insert object values', () => { diff --git a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js index 35a7fc53d0..a353c1f1e1 100644 --- a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js +++ b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js @@ -125,13 +125,13 @@ describe('BinarySearchTreeNode', () => { expect(bstRootNode.toString()).toBe('5,10,20'); - const removedNode1 = bstRootNode.remove(5); + const removed1 = bstRootNode.remove(5); expect(bstRootNode.toString()).toBe('10,20'); - expect(removedNode1.value).toBe(5); + expect(removed1).toBeTruthy(); - const removedNode2 = bstRootNode.remove(20); + const removed2 = bstRootNode.remove(20); expect(bstRootNode.toString()).toBe('10'); - expect(removedNode2.value).toBe(20); + expect(removed2).toBeTruthy(); }); it('should remove nodes with one child', () => { diff --git a/src/data-structures/tree/red-black-tree/RedBlackTree.js b/src/data-structures/tree/red-black-tree/RedBlackTree.js index 2bd3afd46c..6bb47130c8 100644 --- a/src/data-structures/tree/red-black-tree/RedBlackTree.js +++ b/src/data-structures/tree/red-black-tree/RedBlackTree.js @@ -34,7 +34,7 @@ export default class RedBlackTree extends BinarySearchTree { /** * @param {*} value - * @return {BinarySearchTreeNode} + * @return {boolean} */ remove(value) { throw new Error(`Can't remove ${value}. Remove method is not implemented yet`); From 8d3f83cfb7fdf842771a7ee5c67ab9c2b5ab9289 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 13 Jun 2018 07:21:57 +0300 Subject: [PATCH 03/44] Simplify combineWithoutRepetition algorithm. --- .../combinations/combineWithoutRepetitions.js | 81 ++++++------------- 1 file changed, 25 insertions(+), 56 deletions(-) diff --git a/src/algorithms/sets/combinations/combineWithoutRepetitions.js b/src/algorithms/sets/combinations/combineWithoutRepetitions.js index a8217fc5e5..15678ee830 100644 --- a/src/algorithms/sets/combinations/combineWithoutRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithoutRepetitions.js @@ -1,41 +1,31 @@ -/* - @see: https://stackoverflow.com/a/127898/7794070 - - Lets say your array of letters looks like this: "ABCDEFGH". - You have three indices (i, j, k) indicating which letters you - are going to use for the current word, You start with: - - A B C D E F G H - ^ ^ ^ - i j k - - First you vary k, so the next step looks like that: - - A B C D E F G H - ^ ^ ^ - i j k - - If you reached the end you go on and vary j and then k again. - - A B C D E F G H - ^ ^ ^ - i j k +/** + * @param {*[]} comboOptions + * @param {number} comboLength + * @param {*[][]} combos + * @param {*[]} currentCombo + * @return {*[]} + */ +function combineRecursively(comboOptions, comboLength, combos = [], currentCombo = []) { + if (comboLength === 0) { + combos.push(currentCombo); - A B C D E F G H - ^ ^ ^ - i j k + return combos; + } - Once you j reached G you start also to vary i. + for (let letterIndex = 0; letterIndex <= (comboOptions.length - comboLength); letterIndex += 1) { + const letter = comboOptions[letterIndex]; + const restCombinationOptions = comboOptions.slice(letterIndex + 1); - A B C D E F G H - ^ ^ ^ - i j k + combineRecursively( + restCombinationOptions, + comboLength - 1, + combos, + currentCombo.concat([letter]), + ); + } - A B C D E F G H - ^ ^ ^ - i j k - ... - */ + return combos; +} /** * @param {*[]} combinationOptions @@ -43,26 +33,5 @@ * @return {*[]} */ export default function combineWithoutRepetitions(combinationOptions, combinationLength) { - // If combination length is just 1 then return combinationOptions. - if (combinationLength === 1) { - return combinationOptions.map(option => [option]); - } - - // Init combinations array. - const combinations = []; - - for (let i = 0; i <= (combinationOptions.length - combinationLength); i += 1) { - const smallerCombinations = combineWithoutRepetitions( - combinationOptions.slice(i + 1), - combinationLength - 1, - ); - - for (let j = 0; j < smallerCombinations.length; j += 1) { - const combination = [combinationOptions[i]].concat(smallerCombinations[j]); - combinations.push(combination); - } - } - - // Return all calculated combinations. - return combinations; + return combineRecursively(combinationOptions, combinationLength); } From b0c55ec817c17a95d5b8250b5c0c48284d46703a Mon Sep 17 00:00:00 2001 From: Matt Mapplebeck Date: Wed, 13 Jun 2018 01:03:56 -0400 Subject: [PATCH 04/44] add recursive solution to permutations with repetitions problem (#52) * add recursive solution to permutations with repetitions problem * fix untested function, failing test * add comments --- .../__test__/permutateWithRepetitions.test.js | 51 +------------------ .../permutateWithRepetitionsRecursive.test.js | 8 +++ .../testPermutateWithRepetitionsFn.js | 51 +++++++++++++++++++ .../permutateWithRepetitionsRecursive.js | 26 ++++++++++ 4 files changed, 87 insertions(+), 49 deletions(-) create mode 100644 src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js create mode 100644 src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js create mode 100644 src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js index 2984b7c9e3..6cf99eef23 100644 --- a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js +++ b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js @@ -1,55 +1,8 @@ import permutateWithRepetitions from '../permutateWithRepetitions'; +import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn'; describe('permutateWithRepetitions', () => { it('should permutate string with repetition', () => { - const permutations0 = permutateWithRepetitions([]); - expect(permutations0).toEqual([]); - - const permutations1 = permutateWithRepetitions(['A']); - expect(permutations1).toEqual([ - ['A'], - ]); - - const permutations2 = permutateWithRepetitions(['A', 'B']); - expect(permutations2).toEqual([ - ['A', 'A'], - ['A', 'B'], - ['B', 'A'], - ['B', 'B'], - ]); - - const permutations3 = permutateWithRepetitions(['A', 'B', 'C']); - expect(permutations3).toEqual([ - ['A', 'A', 'A'], - ['A', 'A', 'B'], - ['A', 'A', 'C'], - ['A', 'B', 'A'], - ['A', 'B', 'B'], - ['A', 'B', 'C'], - ['A', 'C', 'A'], - ['A', 'C', 'B'], - ['A', 'C', 'C'], - ['B', 'A', 'A'], - ['B', 'A', 'B'], - ['B', 'A', 'C'], - ['B', 'B', 'A'], - ['B', 'B', 'B'], - ['B', 'B', 'C'], - ['B', 'C', 'A'], - ['B', 'C', 'B'], - ['B', 'C', 'C'], - ['C', 'A', 'A'], - ['C', 'A', 'B'], - ['C', 'A', 'C'], - ['C', 'B', 'A'], - ['C', 'B', 'B'], - ['C', 'B', 'C'], - ['C', 'C', 'A'], - ['C', 'C', 'B'], - ['C', 'C', 'C'], - ]); - - const permutations4 = permutateWithRepetitions(['A', 'B', 'C', 'D']); - expect(permutations4.length).toBe(4 * 4 * 4 * 4); + testPermutateWithRepetitionsFn(permutateWithRepetitions); }); }); diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js new file mode 100644 index 0000000000..b4799b7aae --- /dev/null +++ b/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js @@ -0,0 +1,8 @@ +import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive'; +import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn'; + +describe('permutateWithRepetitionsRecursive', () => { + it('should permutate string with repetition', () => { + testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive); + }); +}); diff --git a/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js b/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js new file mode 100644 index 0000000000..c3c14daa7a --- /dev/null +++ b/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js @@ -0,0 +1,51 @@ +export default function testPermutateWithRepetitionsFn(fn) { + const permutations0 = fn([]); + expect(permutations0).toEqual([]); + + const permutations1 = fn(['A']); + expect(permutations1).toEqual([ + ['A'], + ]); + + const permutations2 = fn(['A', 'B']); + expect(permutations2).toEqual([ + ['A', 'A'], + ['A', 'B'], + ['B', 'A'], + ['B', 'B'], + ]); + + const permutations3 = fn(['A', 'B', 'C']); + expect(permutations3).toEqual([ + ['A', 'A', 'A'], + ['A', 'A', 'B'], + ['A', 'A', 'C'], + ['A', 'B', 'A'], + ['A', 'B', 'B'], + ['A', 'B', 'C'], + ['A', 'C', 'A'], + ['A', 'C', 'B'], + ['A', 'C', 'C'], + ['B', 'A', 'A'], + ['B', 'A', 'B'], + ['B', 'A', 'C'], + ['B', 'B', 'A'], + ['B', 'B', 'B'], + ['B', 'B', 'C'], + ['B', 'C', 'A'], + ['B', 'C', 'B'], + ['B', 'C', 'C'], + ['C', 'A', 'A'], + ['C', 'A', 'B'], + ['C', 'A', 'C'], + ['C', 'B', 'A'], + ['C', 'B', 'B'], + ['C', 'B', 'C'], + ['C', 'C', 'A'], + ['C', 'C', 'B'], + ['C', 'C', 'C'], + ]); + + const permutations4 = fn(['A', 'B', 'C', 'D']); + expect(permutations4.length).toBe(4 * 4 * 4 * 4); +} diff --git a/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js b/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js new file mode 100644 index 0000000000..b487efc71c --- /dev/null +++ b/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js @@ -0,0 +1,26 @@ +/** + * @param {*[]} permutationOptions + * @return {*[]} + */ +export default function permutateWithRepetitionsRecursive( + options, + n = options.length || 0, + prefix = [], + perms = [], +) { + // If initial options are null or empty then return empty array + if (!options || !options.length) return []; + + // If no more iterations then add current prefix to perms array + if (n === 0) { + perms.push(prefix); + return perms; + } + + // Recursively find permutations and store in perms array + options.forEach((option) => { + permutateWithRepetitionsRecursive(options, n - 1, prefix.concat([option]), perms); + }); + + return perms; +} From 19f4cc70d3317b695be487392da0c4e0207ad399 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 13 Jun 2018 08:15:21 +0300 Subject: [PATCH 05/44] Add recursive way of generating permutations with repetitions. --- .../__test__/permutateWithRepetitions.test.js | 51 ++++++++++++++++++- .../permutateWithRepetitionsRecursive.test.js | 51 ++++++++++++++++++- .../testPermutateWithRepetitionsFn.js | 51 ------------------- .../permutateWithRepetitionsRecursive.js | 39 +++++++++----- 4 files changed, 123 insertions(+), 69 deletions(-) delete mode 100644 src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js index 6cf99eef23..2984b7c9e3 100644 --- a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js +++ b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js @@ -1,8 +1,55 @@ import permutateWithRepetitions from '../permutateWithRepetitions'; -import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn'; describe('permutateWithRepetitions', () => { it('should permutate string with repetition', () => { - testPermutateWithRepetitionsFn(permutateWithRepetitions); + const permutations0 = permutateWithRepetitions([]); + expect(permutations0).toEqual([]); + + const permutations1 = permutateWithRepetitions(['A']); + expect(permutations1).toEqual([ + ['A'], + ]); + + const permutations2 = permutateWithRepetitions(['A', 'B']); + expect(permutations2).toEqual([ + ['A', 'A'], + ['A', 'B'], + ['B', 'A'], + ['B', 'B'], + ]); + + const permutations3 = permutateWithRepetitions(['A', 'B', 'C']); + expect(permutations3).toEqual([ + ['A', 'A', 'A'], + ['A', 'A', 'B'], + ['A', 'A', 'C'], + ['A', 'B', 'A'], + ['A', 'B', 'B'], + ['A', 'B', 'C'], + ['A', 'C', 'A'], + ['A', 'C', 'B'], + ['A', 'C', 'C'], + ['B', 'A', 'A'], + ['B', 'A', 'B'], + ['B', 'A', 'C'], + ['B', 'B', 'A'], + ['B', 'B', 'B'], + ['B', 'B', 'C'], + ['B', 'C', 'A'], + ['B', 'C', 'B'], + ['B', 'C', 'C'], + ['C', 'A', 'A'], + ['C', 'A', 'B'], + ['C', 'A', 'C'], + ['C', 'B', 'A'], + ['C', 'B', 'B'], + ['C', 'B', 'C'], + ['C', 'C', 'A'], + ['C', 'C', 'B'], + ['C', 'C', 'C'], + ]); + + const permutations4 = permutateWithRepetitions(['A', 'B', 'C', 'D']); + expect(permutations4.length).toBe(4 * 4 * 4 * 4); }); }); diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js index b4799b7aae..62b412320d 100644 --- a/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js +++ b/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js @@ -1,8 +1,55 @@ import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive'; -import testPermutateWithRepetitionsFn from './testPermutateWithRepetitionsFn'; describe('permutateWithRepetitionsRecursive', () => { it('should permutate string with repetition', () => { - testPermutateWithRepetitionsFn(permutateWithRepetitionsRecursive); + const permutations0 = permutateWithRepetitionsRecursive([]); + expect(permutations0).toEqual([]); + + const permutations1 = permutateWithRepetitionsRecursive(['A']); + expect(permutations1).toEqual([ + ['A'], + ]); + + const permutations2 = permutateWithRepetitionsRecursive(['A', 'B']); + expect(permutations2).toEqual([ + ['A', 'A'], + ['A', 'B'], + ['B', 'A'], + ['B', 'B'], + ]); + + const permutations3 = permutateWithRepetitionsRecursive(['A', 'B', 'C']); + expect(permutations3).toEqual([ + ['A', 'A', 'A'], + ['A', 'A', 'B'], + ['A', 'A', 'C'], + ['A', 'B', 'A'], + ['A', 'B', 'B'], + ['A', 'B', 'C'], + ['A', 'C', 'A'], + ['A', 'C', 'B'], + ['A', 'C', 'C'], + ['B', 'A', 'A'], + ['B', 'A', 'B'], + ['B', 'A', 'C'], + ['B', 'B', 'A'], + ['B', 'B', 'B'], + ['B', 'B', 'C'], + ['B', 'C', 'A'], + ['B', 'C', 'B'], + ['B', 'C', 'C'], + ['C', 'A', 'A'], + ['C', 'A', 'B'], + ['C', 'A', 'C'], + ['C', 'B', 'A'], + ['C', 'B', 'B'], + ['C', 'B', 'C'], + ['C', 'C', 'A'], + ['C', 'C', 'B'], + ['C', 'C', 'C'], + ]); + + const permutations4 = permutateWithRepetitionsRecursive(['A', 'B', 'C', 'D']); + expect(permutations4.length).toBe(4 * 4 * 4 * 4); }); }); diff --git a/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js b/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js deleted file mode 100644 index c3c14daa7a..0000000000 --- a/src/algorithms/sets/permutations/__test__/testPermutateWithRepetitionsFn.js +++ /dev/null @@ -1,51 +0,0 @@ -export default function testPermutateWithRepetitionsFn(fn) { - const permutations0 = fn([]); - expect(permutations0).toEqual([]); - - const permutations1 = fn(['A']); - expect(permutations1).toEqual([ - ['A'], - ]); - - const permutations2 = fn(['A', 'B']); - expect(permutations2).toEqual([ - ['A', 'A'], - ['A', 'B'], - ['B', 'A'], - ['B', 'B'], - ]); - - const permutations3 = fn(['A', 'B', 'C']); - expect(permutations3).toEqual([ - ['A', 'A', 'A'], - ['A', 'A', 'B'], - ['A', 'A', 'C'], - ['A', 'B', 'A'], - ['A', 'B', 'B'], - ['A', 'B', 'C'], - ['A', 'C', 'A'], - ['A', 'C', 'B'], - ['A', 'C', 'C'], - ['B', 'A', 'A'], - ['B', 'A', 'B'], - ['B', 'A', 'C'], - ['B', 'B', 'A'], - ['B', 'B', 'B'], - ['B', 'B', 'C'], - ['B', 'C', 'A'], - ['B', 'C', 'B'], - ['B', 'C', 'C'], - ['C', 'A', 'A'], - ['C', 'A', 'B'], - ['C', 'A', 'C'], - ['C', 'B', 'A'], - ['C', 'B', 'B'], - ['C', 'B', 'C'], - ['C', 'C', 'A'], - ['C', 'C', 'B'], - ['C', 'C', 'C'], - ]); - - const permutations4 = fn(['A', 'B', 'C', 'D']); - expect(permutations4.length).toBe(4 * 4 * 4 * 4); -} diff --git a/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js b/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js index b487efc71c..f379c7cefd 100644 --- a/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js +++ b/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js @@ -1,26 +1,37 @@ /** * @param {*[]} permutationOptions + * @param {number} permutationLength + * @param {*[]} currentPermutation + * @param {*[][]} permutations * @return {*[]} */ export default function permutateWithRepetitionsRecursive( - options, - n = options.length || 0, - prefix = [], - perms = [], + permutationOptions, + permutationLength = permutationOptions.length || 0, + currentPermutation = [], + permutations = [], ) { - // If initial options are null or empty then return empty array - if (!options || !options.length) return []; + // If initial options are null or empty then return empty array. + if (!permutationOptions || !permutationOptions.length) { + return []; + } + + // If no more iterations required then add current permutation to permutations array. + if (permutationLength === 0) { + permutations.push(currentPermutation); - // If no more iterations then add current prefix to perms array - if (n === 0) { - perms.push(prefix); - return perms; + return permutations; } - // Recursively find permutations and store in perms array - options.forEach((option) => { - permutateWithRepetitionsRecursive(options, n - 1, prefix.concat([option]), perms); + // Recursively find permutations and store in permutations array. + permutationOptions.forEach((permutationOption) => { + permutateWithRepetitionsRecursive( + permutationOptions, + permutationLength - 1, + currentPermutation.concat([permutationOption]), + permutations, + ); }); - return perms; + return permutations; } From d154015cda44a820ec16d5c6306587cc848bda53 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 14 Jun 2018 07:59:47 +0300 Subject: [PATCH 06/44] Code style fixes. --- src/algorithms/math/fibonacci/fibonacci.js | 2 +- src/algorithms/math/fibonacci/fibonacciNth.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/algorithms/math/fibonacci/fibonacci.js b/src/algorithms/math/fibonacci/fibonacci.js index 3230dfddd6..4caa1d9bd6 100644 --- a/src/algorithms/math/fibonacci/fibonacci.js +++ b/src/algorithms/math/fibonacci/fibonacci.js @@ -18,7 +18,7 @@ export default function fibonacci(n) { while (iterationsCounter) { currentValue += previousValue; - previousValue = (currentValue - previousValue); + previousValue = currentValue - previousValue; fibSequence.push(currentValue); diff --git a/src/algorithms/math/fibonacci/fibonacciNth.js b/src/algorithms/math/fibonacci/fibonacciNth.js index 76bbbe871d..729224470a 100644 --- a/src/algorithms/math/fibonacci/fibonacciNth.js +++ b/src/algorithms/math/fibonacci/fibonacciNth.js @@ -16,7 +16,7 @@ export default function fibonacciNth(n) { while (iterationsCounter) { currentValue += previousValue; - previousValue = (currentValue - previousValue); + previousValue = currentValue - previousValue; iterationsCounter -= 1; } From 6d413d897d5c81ba3ab9cef9de3c6c1e23a9330b Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 18 Jun 2018 15:44:50 +0300 Subject: [PATCH 07/44] Update javascript-algorithms-and-data-structures version. --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 5b229954fc..e7be343899 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "javascript-algorithms-and-data-structures", - "version": "0.0.3", + "version": "0.0.4", "lockfileVersion": 1, "requires": true, "dependencies": { From 8c206a9976994218824b0425348be90034a17f0f Mon Sep 17 00:00:00 2001 From: Sina Sharafzadeh Date: Mon, 18 Jun 2018 17:20:02 +0430 Subject: [PATCH 08/44] fix unbound knapsack problem with items more than 1(default value) (#73) --- .../sets/knapsack-problem/Knapsack.js | 5 +- .../__test__/Knapsack.test.js | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/algorithms/sets/knapsack-problem/Knapsack.js b/src/algorithms/sets/knapsack-problem/Knapsack.js index d23e12e0fb..10ce6334b3 100644 --- a/src/algorithms/sets/knapsack-problem/Knapsack.js +++ b/src/algorithms/sets/knapsack-problem/Knapsack.js @@ -165,7 +165,10 @@ export default class Knapsack { const availableWeight = this.weightLimit - this.totalWeight; const maxPossibleItemsCount = Math.floor(availableWeight / currentItem.weight); - if (maxPossibleItemsCount) { + if (maxPossibleItemsCount > currentItem.itemsInStock) { + currentItem.quantity = currentItem.itemsInStock; + this.selectedItems.push(currentItem); + } else if (maxPossibleItemsCount) { currentItem.quantity = maxPossibleItemsCount; this.selectedItems.push(currentItem); } diff --git a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js index 9569908f45..d322445a72 100644 --- a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js +++ b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js @@ -96,6 +96,31 @@ describe('Knapsack', () => { new KnapsackItem({ value: 20, weight: 2 }), // v/w ratio is 10 ]; + const maxKnapsackWeight = 15; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveUnboundedKnapsackProblem(); + + expect(knapsack.totalValue).toBe(84 + 20 + 12 + 10 + 5); + expect(knapsack.totalWeight).toBe(15); + expect(knapsack.selectedItems.length).toBe(5); + expect(knapsack.selectedItems[0].toString()).toBe('v84 w7 x 1'); + expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 1'); + expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 1'); + expect(knapsack.selectedItems[3].toString()).toBe('v12 w3 x 1'); + expect(knapsack.selectedItems[4].toString()).toBe('v5 w2 x 1'); + }); + + it('should solve unbound knapsack problem with items in stock', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 84, weight: 7, itemsInStock: 3 }), // v/w ratio is 12 + new KnapsackItem({ value: 5, weight: 2, itemsInStock: 2 }), // v/w ratio is 2.5 + new KnapsackItem({ value: 12, weight: 3, itemsInStock: 1 }), // v/w ratio is 4 + new KnapsackItem({ value: 10, weight: 1, itemsInStock: 6 }), // v/w ratio is 10 + new KnapsackItem({ value: 20, weight: 2, itemsInStock: 8 }), // v/w ratio is 10 + ]; + const maxKnapsackWeight = 17; const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); @@ -109,4 +134,29 @@ describe('Knapsack', () => { expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 1'); expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 1'); }); + + it('should solve unbound knapsack problem with items in stock and max weight more than sum of all items', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 84, weight: 7, itemsInStock: 3 }), // v/w ratio is 12 + new KnapsackItem({ value: 5, weight: 2, itemsInStock: 2 }), // v/w ratio is 2.5 + new KnapsackItem({ value: 12, weight: 3, itemsInStock: 1 }), // v/w ratio is 4 + new KnapsackItem({ value: 10, weight: 1, itemsInStock: 6 }), // v/w ratio is 10 + new KnapsackItem({ value: 20, weight: 2, itemsInStock: 8 }), // v/w ratio is 10 + ]; + + const maxKnapsackWeight = 60; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveUnboundedKnapsackProblem(); + + expect(knapsack.totalValue).toBe((3 * 84) + (2 * 5) + (1 * 12) + (6 * 10) + (8 * 20)); + expect(knapsack.totalWeight).toBe((3 * 7) + (2 * 2) + (1 * 3) + (6 * 1) + (8 * 2)); + expect(knapsack.selectedItems.length).toBe(5); + expect(knapsack.selectedItems[0].toString()).toBe('v84 w7 x 3'); + expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 8'); + expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 6'); + expect(knapsack.selectedItems[3].toString()).toBe('v12 w3 x 1'); + expect(knapsack.selectedItems[4].toString()).toBe('v5 w2 x 2'); + }); }); From 98092ee43f6da477502ed763f679c7d0d40b65fc Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 18 Jun 2018 15:57:45 +0300 Subject: [PATCH 09/44] Code style fixes. --- src/algorithms/sets/knapsack-problem/Knapsack.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/algorithms/sets/knapsack-problem/Knapsack.js b/src/algorithms/sets/knapsack-problem/Knapsack.js index 10ce6334b3..9085895702 100644 --- a/src/algorithms/sets/knapsack-problem/Knapsack.js +++ b/src/algorithms/sets/knapsack-problem/Knapsack.js @@ -166,12 +166,16 @@ export default class Knapsack { const maxPossibleItemsCount = Math.floor(availableWeight / currentItem.weight); if (maxPossibleItemsCount > currentItem.itemsInStock) { + // If we have more items in stock then it is allowed to add + // let's add the maximum allowed number of them. currentItem.quantity = currentItem.itemsInStock; - this.selectedItems.push(currentItem); } else if (maxPossibleItemsCount) { + // In case if we don't have specified number of items in stock + // let's add only items we have in stock. currentItem.quantity = maxPossibleItemsCount; - this.selectedItems.push(currentItem); } + + this.selectedItems.push(currentItem); } } } From 9311735867b882110da6350cfb9cc2210b9bd8b5 Mon Sep 17 00:00:00 2001 From: m-maksyutin Date: Mon, 18 Jun 2018 16:30:30 +0300 Subject: [PATCH 10/44] Correct a comment (#66) * Fix LinkedList * Fix the prepend method for the LinkedList * Fix the remove method for the MinHeap * Correct a comment --- src/data-structures/tree/BinaryTreeNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data-structures/tree/BinaryTreeNode.js b/src/data-structures/tree/BinaryTreeNode.js index 71e7ae0d3f..9205e4820e 100644 --- a/src/data-structures/tree/BinaryTreeNode.js +++ b/src/data-structures/tree/BinaryTreeNode.js @@ -69,7 +69,7 @@ export default class BinaryTreeNode { return undefined; } - // Check if grand-parent has more than two children. + // Check if grand-parent has two children. if (!this.parent.parent.left || !this.parent.parent.right) { return undefined; } From 87e59bf4b0094c9368446762f3fbf815e82ac9f4 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 18 Jun 2018 17:05:53 +0300 Subject: [PATCH 11/44] Add algorithms complexity to README. --- README.md | 198 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 95a10f8e94..94d40ef4b1 100644 --- a/README.md +++ b/README.md @@ -21,91 +21,95 @@ be accessed and modified efficiently. More precisely, a data structure is a coll values, the relationships among them, and the functions or operations that can be applied to the data. -* [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list) -* [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue) -* [Stack](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) -* [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) -* [Heap](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) -* [Priority Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) -* [Trie](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) -* [Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) - * [Binary Search Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) - * [AVL Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) - * [Red-Black Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/red-black-tree) - * [Segment Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/segment-tree) - with min/max/sum range queries examples - * [Fenwick Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/fenwick-tree) (Binary Indexed Tree) -* [Graph](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/graph) (both directed and undirected) -* [Disjoint Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/disjoint-set) +`B` - Beginner, `A` - Advanced + +* `B` [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list) +* `B` [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue) +* `B` [Stack](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) +* `B` [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) +* `B` [Heap](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) +* `B` [Priority Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) +* `A` [Trie](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) +* `A` [Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) + * `A` [Binary Search Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) + * `A` [AVL Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) + * `A` [Red-Black Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/red-black-tree) + * `A` [Segment Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/segment-tree) - with min/max/sum range queries examples + * `A` [Fenwick Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/fenwick-tree) (Binary Indexed Tree) +* `A` [Graph](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/graph) (both directed and undirected) +* `A` [Disjoint Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/disjoint-set) ## Algorithms An algorithm is an unambiguous specification of how to solve a class of problems. It is a set of rules that precisely define a sequence of operations. +`B` - Beginner, `A` - Advanced + ### Algorithms by Topic * **Math** - * [Factorial](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial) - * [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (trial division method) - * [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) - * [Least Common Multiple](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM) - * [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit - * [Is Power of Two](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms) - * [Liu Hui π Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/liu-hui) - approximate π calculations based on N-gons + * `B` [Factorial](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial) + * `B` [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) + * `B` [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (trial division method) + * `B` [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * `B` [Least Common Multiple](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM) + * `A` [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) + * `B` [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit + * `B` [Is Power of Two](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms) + * `A` [Liu Hui π Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/liu-hui) - approximate π calculations based on N-gons * **Sets** - * [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets - * [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set - * [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) - * [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) - * [Fisher–Yates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence - * [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence) (LCS) - * [Longest Increasing Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS) - * [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones - * [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" (Kadane's) versions + * `B` [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets + * `A` [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set + * `A` [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) + * `A` [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) + * `B` [Fisher–Yates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence + * `A` [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence) (LCS) + * `A` [Longest Increasing Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) + * `A` [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS) + * `A` [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones + * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" (Kadane's) versions * **Strings** - * [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences - * [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different - * [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search - * [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search - * [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) + * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences + * `B` [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different + * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search + * `A` [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search + * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) * **Searches** - * [Linear Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/linear-search) - * [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) + * `B` [Linear Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/linear-search) + * `B` [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) * **Sorting** - * [Bubble Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort) - * [Selection Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort) - * [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) - * [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) - * [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - in-place and non-in-place implementations - * [Shellsort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort) - * [Counting Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/counting-sort) - * [Radix Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/radix-sort) + * `B` [Bubble Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort) + * `B` [Selection Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort) + * `B` [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) + * `B` [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) + * `B` [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) + * `B` [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - in-place and non-in-place implementations + * `B` [Shellsort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort) + * `A` [Counting Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/counting-sort) + * `A` [Radix Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/radix-sort) * **Trees** - * [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/breadth-first-search) (BFS) + * `B` [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) + * `B` [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/breadth-first-search) (BFS) * **Graphs** - * [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) - * [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/breadth-first-search) (BFS) - * [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices - * [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices - * [Detect Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) - * [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [Topological Sorting](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/topological-sorting) - DFS method - * [Articulation Points](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) - * [Bridges](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bridges) - DFS based algorithm - * [Eulerian Path and Eulerian Circuit](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once - * [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * [Strongly Connected Components](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm - * [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * `B` [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) + * `B` [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/breadth-first-search) (BFS) + * `A` [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices + * `A` [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * `A` [Detect Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) + * `A` [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `B` [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Topological Sorting](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/topological-sorting) - DFS method + * `A` [Articulation Points](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) + * `A` [Bridges](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bridges) - DFS based algorithm + * `A` [Eulerian Path and Eulerian Circuit](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once + * `A` [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * `A` [Strongly Connected Components](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm + * `A` [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **Uncategorized** - * [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * `B` [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) + * `A` [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) + * `A` [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) ### Algorithms by Paradigm @@ -114,40 +118,40 @@ of algorithms. It is an abstraction higher than the notion of an algorithm, just algorithm is an abstraction higher than a computer program. * **Brute Force** - look at all the possibilities and selects the best solution - * [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) + * `A` [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **Greedy** - choose the best option at the current time, without any consideration for the future - * [Unbound Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices - * [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Unbound Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) + * `A` [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices + * `A` [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph * **Divide and Conquer** - divide the problem into smaller parts and then solve those parts - * [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) - * [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) - * [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) - * [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) - * [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * [Tree Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [Graph Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) + * `B` [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) + * `B` [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) + * `B` [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * `A` [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) + * `A` [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) + * `B` [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) + * `B` [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) + * `B` [Tree Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) + * `B` [Graph Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) * **Dynamic Programming** - build up a solution using previously found sub-solutions - * [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences - * [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS) - * [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) - * [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) - * [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * `B` [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) + * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences + * `A` [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS) + * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) + * `A` [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) + * `A` [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) + * `A` [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) + * `A` [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) + * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) + * `A` [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices * **Backtracking** - similarly to brute force, try to generate all possible solutions, but each time you generate next solution you test if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a different path of finding a solution. Normally the DFS traversal of state-space is being used. - * [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * `A` [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * `A` [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) + * `A` [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) * **Branch & Bound** - remember the lowest-cost solution found at each stage of the backtracking search, and use the cost of the lowest-cost solution found so far as a lower bound on the cost of a least-cost solution to the problem, in order to discard partial solutions with costs larger than the From d74234d597f1712bd8d6a3e6d050cf7ec660d80f Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Tue, 19 Jun 2018 08:32:30 +0300 Subject: [PATCH 12/44] Update README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94d40ef4b1..740aae038b 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ a set of rules that precisely define a sequence of operations. * **Strings** * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences * `B` [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different - * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - substring search + * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) (KMP Algorithm) - substring search * `A` [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) * **Searches** From 9e210ae56003b90ffa4f1aa2e877ed68e09bd4cb Mon Sep 17 00:00:00 2001 From: hariv Date: Thu, 21 Jun 2018 06:42:13 -0700 Subject: [PATCH 13/44] Z algorithm implementation (#77) * Implemented Z algorithm * Fixed bugs in implementation and added tests * Added README explaining z algorithm --- src/algorithms/string/z-algorithm/README.md | 27 +++++++++ .../z-algorithm/__test__/zAlgorithm.test.js | 12 ++++ .../string/z-algorithm/zAlgorithm.js | 57 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/algorithms/string/z-algorithm/README.md create mode 100644 src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js create mode 100644 src/algorithms/string/z-algorithm/zAlgorithm.js diff --git a/src/algorithms/string/z-algorithm/README.md b/src/algorithms/string/z-algorithm/README.md new file mode 100644 index 0000000000..733ebf5cd1 --- /dev/null +++ b/src/algorithms/string/z-algorithm/README.md @@ -0,0 +1,27 @@ +# Z-algorithm + +The Z-algorithm finds occurrences of a "word" `W` +within a main "text string" `T` in linear time. + +Given a string `S` of length `n`, the algorithm produces +an array, `Z` where `Z[i]` represents the ongest substring +starting from `S[i]` which is also a prefix of `S`. Finding +`Z` for the string obtained by concatenating the word, `W` +with a nonce character, say `$` followed by the text, `T`, +helps with pattern matching, for if there is some index `i` +such that `Z[i]` equals the pattern length, then the pattern +must be present at that point. + +While the `Z` array can be computed with two nested loops, the +following strategy shows how to obtain it in linear time, based +on the idea that as we iterate over the letters in the string +(index `i` from `1` to `n - 1`), we maintain an interval `[L, R]` +which is the interval with maximum `R` such that `1 ≤ L ≤ i ≤ R` +and `S[L...R]` is a prefix that is also a substring (if no such +interval exists, just let `L = R =  - 1`). For `i = 1`, we can +simply compute `L` and `R` by comparing `S[0...]` to `S[1...]`. + +## Complexity + +- **Time:** `O(|W| + |T|)` +- **Space:** `O(|W|)` \ No newline at end of file diff --git a/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js new file mode 100644 index 0000000000..d58ff75bc9 --- /dev/null +++ b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js @@ -0,0 +1,12 @@ +import zAlgorithm from '../zAlgorithm'; + +describe('zAlgorithm', () => { + it('should find word position in given text', () => { + expect(zAlgorithm('abcbcglx', 'abca')).toBe(-1); + expect(zAlgorithm('abcbcglx', 'bcgl')).toBe(3); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabcy')).toBe(15); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabca')).toBe(-1); + expect(zAlgorithm('abcxabcdabxaabcdabcabcdabcdabcy', 'abcdabca')).toBe(12); + expect(zAlgorithm('abcxabcdabxaabaabaaaabcdabcdabcy', 'aabaabaaa')).toBe(11); + }); +}); diff --git a/src/algorithms/string/z-algorithm/zAlgorithm.js b/src/algorithms/string/z-algorithm/zAlgorithm.js new file mode 100644 index 0000000000..f93318ce43 --- /dev/null +++ b/src/algorithms/string/z-algorithm/zAlgorithm.js @@ -0,0 +1,57 @@ +/** + * @param {string} word + * @param {string} text + * @return {number[]} + */ + +function buildZArray(word, text) { + const zString = `${word}$${text}`; + const zArray = new Array(zString.length); + let left = 0; + let right = 0; + let k = 0; + + for (let i = 1; i < zString.length; i += 1) { + if (i > right) { + left = i; + right = i; + + while (right < zString.length && zString[right - left] === zString[right]) { + right += 1; + } + + zArray[i] = right - left; + right -= 1; + } else { + k = i - left; + if (zArray[k] < (right - i) + 1) { + zArray[i] = zArray[k]; + } else { + left = i; + while (right < zString.length && zString[right - left] === zString[right]) { + right += 1; + } + + zArray[i] = right - left; + right -= 1; + } + } + } + + return zArray; +} + +/** + * @param {string} text + * @param {string} word + * @return {number} + */ +export default function zAlgorithm(text, word) { + const zArray = buildZArray(word, text); + for (let i = 1; i < zArray.length; i += 1) { + if (zArray[i] === word.length) { + return (i - word.length - 1); + } + } + return -1; +} From 5bdcbb397d0440b3a67970927cd86d9a2d44db1d Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 21 Jun 2018 16:59:20 +0300 Subject: [PATCH 14/44] Code style fixes. --- README.md | 3 +- .../z-algorithm/__test__/zAlgorithm.test.js | 18 ++++---- .../string/z-algorithm/zAlgorithm.js | 41 ++++++++++++++----- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 740aae038b..690c80ab08 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ a set of rules that precisely define a sequence of operations. * **Strings** * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences * `B` [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different - * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) (KMP Algorithm) - substring search + * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) (KMP Algorithm) - substring search (pattern matching) + * `A` [Z Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/z-algorithm) - substring search (pattern matching) * `A` [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) * **Searches** diff --git a/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js index d58ff75bc9..9ef1e3f4b4 100644 --- a/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js +++ b/src/algorithms/string/z-algorithm/__test__/zAlgorithm.test.js @@ -1,12 +1,16 @@ import zAlgorithm from '../zAlgorithm'; describe('zAlgorithm', () => { - it('should find word position in given text', () => { - expect(zAlgorithm('abcbcglx', 'abca')).toBe(-1); - expect(zAlgorithm('abcbcglx', 'bcgl')).toBe(3); - expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabcy')).toBe(15); - expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabca')).toBe(-1); - expect(zAlgorithm('abcxabcdabxaabcdabcabcdabcdabcy', 'abcdabca')).toBe(12); - expect(zAlgorithm('abcxabcdabxaabaabaaaabcdabcdabcy', 'aabaabaaa')).toBe(11); + it('should find word positions in given text', () => { + expect(zAlgorithm('abcbcglx', 'abca')).toEqual([]); + expect(zAlgorithm('abca', 'abca')).toEqual([0]); + expect(zAlgorithm('abca', 'abcadfd')).toEqual([]); + expect(zAlgorithm('abcbcglabcx', 'abc')).toEqual([0, 7]); + expect(zAlgorithm('abcbcglx', 'bcgl')).toEqual([3]); + expect(zAlgorithm('abcbcglx', 'cglx')).toEqual([4]); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabcy')).toEqual([15]); + expect(zAlgorithm('abcxabcdabxabcdabcdabcy', 'abcdabca')).toEqual([]); + expect(zAlgorithm('abcxabcdabxaabcdabcabcdabcdabcy', 'abcdabca')).toEqual([12]); + expect(zAlgorithm('abcxabcdabxaabaabaaaabcdabcdabcy', 'aabaabaaa')).toEqual([11]); }); }); diff --git a/src/algorithms/string/z-algorithm/zAlgorithm.js b/src/algorithms/string/z-algorithm/zAlgorithm.js index f93318ce43..743e085dbe 100644 --- a/src/algorithms/string/z-algorithm/zAlgorithm.js +++ b/src/algorithms/string/z-algorithm/zAlgorithm.js @@ -1,12 +1,13 @@ +// The string separator that is being used for "word" and "text" concatenation. +const SEPARATOR = '$'; + /** - * @param {string} word - * @param {string} text + * @param {string} zString * @return {number[]} */ - -function buildZArray(word, text) { - const zString = `${word}$${text}`; +function buildZArray(zString) { const zArray = new Array(zString.length); + let left = 0; let right = 0; let k = 0; @@ -44,14 +45,32 @@ function buildZArray(word, text) { /** * @param {string} text * @param {string} word - * @return {number} + * @return {number[]} */ export default function zAlgorithm(text, word) { - const zArray = buildZArray(word, text); - for (let i = 1; i < zArray.length; i += 1) { - if (zArray[i] === word.length) { - return (i - word.length - 1); + // The list of word's positions in text. Word may be found in the same text + // in several different positions. Thus it is an array. + const wordPositions = []; + + // Concatenate word and string. Word will be a prefix to a string. + const zString = `${word}${SEPARATOR}${text}`; + + // Generate Z-array for concatenated string. + const zArray = buildZArray(zString); + + // Based on Z-array properties each cell will tell us the length of the match between + // the string prefix and current sub-text. Thus we're may find all positions in zArray + // with the number that equals to the length of the word (zString prefix) and based on + // that positions we'll be able to calculate word positions in text. + for (let charIndex = 1; charIndex < zArray.length; charIndex += 1) { + if (zArray[charIndex] === word.length) { + // Since we did concatenation to form zString we need to subtract prefix + // and separator lengths. + const wordPosition = charIndex - word.length - SEPARATOR.length; + wordPositions.push(wordPosition); } } - return -1; + + // Return the list of word positions. + return wordPositions; } From 81d17bc4f91f8e72e29bfc752c211f43944666d4 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 21 Jun 2018 17:48:35 +0300 Subject: [PATCH 15/44] Add comments. --- .../string/z-algorithm/zAlgorithm.js | 96 +++++++++++++++---- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/src/algorithms/string/z-algorithm/zAlgorithm.js b/src/algorithms/string/z-algorithm/zAlgorithm.js index 743e085dbe..1c532f5f8f 100644 --- a/src/algorithms/string/z-algorithm/zAlgorithm.js +++ b/src/algorithms/string/z-algorithm/zAlgorithm.js @@ -6,39 +6,95 @@ const SEPARATOR = '$'; * @return {number[]} */ function buildZArray(zString) { - const zArray = new Array(zString.length); + // Initiate zArray and fill it with zeros. + const zArray = new Array(zString.length).fill(null).map(() => 0); - let left = 0; - let right = 0; - let k = 0; + // Z box boundaries. + let zBoxLeftIndex = 0; + let zBoxRightIndex = 0; - for (let i = 1; i < zString.length; i += 1) { - if (i > right) { - left = i; - right = i; + // Position of current zBox character that is also a position of + // the same character in prefix. + // For example: + // Z string: ab$xxabxx + // Indices: 012345678 + // Prefix: ab....... + // Z box: .....ab.. + // Z box shift for 'a' would be 0 (0-position in prefix and 0-position in Z box) + // Z box shift for 'b' would be 1 (1-position in prefix and 1-position in Z box) + let zBoxShift = 0; - while (right < zString.length && zString[right - left] === zString[right]) { - right += 1; + // Go through all characters of the zString. + for (let charIndex = 1; charIndex < zString.length; charIndex += 1) { + if (charIndex > zBoxRightIndex) { + // We're OUTSIDE of Z box. In other words this is a case when we're + // starting from Z box of size 1. + + // In this case let's make current character to be a Z box of length 1. + zBoxLeftIndex = charIndex; + zBoxRightIndex = charIndex; + + // Now let's go and check current and the following characters to see if + // they are the same as a prefix. By doing this we will also expand our + // Z box. For example if starting from current position we will find 3 + // more characters that are equal to the ones in the prefix we will expand + // right Z box boundary by 3. + while ( + zBoxRightIndex < zString.length && + zString[zBoxRightIndex - zBoxLeftIndex] === zString[zBoxRightIndex] + ) { + // Expanding Z box right boundary. + zBoxRightIndex += 1; } - zArray[i] = right - left; - right -= 1; + // Now we may calculate how many characters starting from current position + // are are the same as the prefix. We may calculate it by difference between + // right and left Z box boundaries. + zArray[charIndex] = zBoxRightIndex - zBoxLeftIndex; + + // Move right Z box boundary left by one position just because we've used + // [zBoxRightIndex - zBoxLeftIndex] index calculation above. + zBoxRightIndex -= 1; } else { - k = i - left; - if (zArray[k] < (right - i) + 1) { - zArray[i] = zArray[k]; + // We're INSIDE of Z box. + + // Calculate corresponding Z box shift. Because we want to copy the values + // from zArray that have been calculated before. + zBoxShift = charIndex - zBoxLeftIndex; + + // Check if the value that has been already calculated before + // leaves us inside of Z box or it goes beyond the checkbox + // right boundary. + if (zArray[zBoxShift] < (zBoxRightIndex - charIndex) + 1) { + // If calculated value don't force us to go outside Z box + // then we're safe and we may simply use previously calculated value. + zArray[charIndex] = zArray[zBoxShift]; } else { - left = i; - while (right < zString.length && zString[right - left] === zString[right]) { - right += 1; + // In case if previously calculated values forces us to go outside of Z box + // we can't safely copy previously calculated zArray value. It is because + // we are sure that there is no further prefix matches outside of Z box. + // Thus such values must be re-calculated and reduced to certain point. + + // To do so we need to shift left boundary of Z box to current position. + zBoxLeftIndex = charIndex; + + // And start comparing characters one by one as we normally do for the case + // when we are outside of checkbox. + while ( + zBoxRightIndex < zString.length && + zString[zBoxRightIndex - zBoxLeftIndex] === zString[zBoxRightIndex] + ) { + zBoxRightIndex += 1; } - zArray[i] = right - left; - right -= 1; + zArray[charIndex] = zBoxRightIndex - zBoxLeftIndex; + + zBoxRightIndex -= 1; } } } + // Return generated zArray. return zArray; } From e55823147480281aec952ce0e0bd5b6dcbf75229 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 21 Jun 2018 17:59:31 +0300 Subject: [PATCH 16/44] Add comments. --- src/algorithms/string/z-algorithm/README.md | 45 ++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/algorithms/string/z-algorithm/README.md b/src/algorithms/string/z-algorithm/README.md index 733ebf5cd1..0f12bc7333 100644 --- a/src/algorithms/string/z-algorithm/README.md +++ b/src/algorithms/string/z-algorithm/README.md @@ -1,10 +1,10 @@ -# Z-algorithm +# Z Algorithm The Z-algorithm finds occurrences of a "word" `W` -within a main "text string" `T` in linear time. +within a main "text string" `T` in linear time `O(|W| + |T|)`. Given a string `S` of length `n`, the algorithm produces -an array, `Z` where `Z[i]` represents the ongest substring +an array, `Z` where `Z[i]` represents the longest substring starting from `S[i]` which is also a prefix of `S`. Finding `Z` for the string obtained by concatenating the word, `W` with a nonce character, say `$` followed by the text, `T`, @@ -12,7 +12,7 @@ helps with pattern matching, for if there is some index `i` such that `Z[i]` equals the pattern length, then the pattern must be present at that point. -While the `Z` array can be computed with two nested loops, the +While the `Z` array can be computed with two nested loops in `O(|W| * |T|)` time, the following strategy shows how to obtain it in linear time, based on the idea that as we iterate over the letters in the string (index `i` from `1` to `n - 1`), we maintain an interval `[L, R]` @@ -21,7 +21,42 @@ and `S[L...R]` is a prefix that is also a substring (if no such interval exists, just let `L = R =  - 1`). For `i = 1`, we can simply compute `L` and `R` by comparing `S[0...]` to `S[1...]`. +**Example of Z array** + +``` +Index 0 1 2 3 4 5 6 7 8 9 10 11 +Text a a b c a a b x a a a z +Z values X 1 0 0 3 1 0 0 2 2 1 0 +``` + +Other examples + +``` +str = a a a a a a +Z[] = x 5 4 3 2 1 +``` + +``` +str = a a b a a c d +Z[] = x 1 0 2 1 0 0 +``` + +``` +str = a b a b a b a b +Z[] = x 0 6 0 4 0 2 0 +``` + +**Example of Z box** + +![z-box](https://ivanyu.me/wp-content/uploads/2014/09/zalg1.png) + ## Complexity - **Time:** `O(|W| + |T|)` -- **Space:** `O(|W|)` \ No newline at end of file +- **Space:** `O(|W|)` + +## References + +- [GeeksForGeeks](https://www.geeksforgeeks.org/z-algorithm-linear-time-pattern-searching-algorithm/) +- [YouTube](https://www.youtube.com/watch?v=CpZh4eF8QBw&t=0s&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=70) +- [Z Algorithm by Ivan Yurchenko](https://ivanyu.me/blog/2013/10/15/z-algorithm/) From bd5a16be719ba41baabb81def69bd86c14e2dde2 Mon Sep 17 00:00:00 2001 From: m-maksyutin Date: Fri, 22 Jun 2018 07:57:52 +0300 Subject: [PATCH 17/44] Fix BST removal method (#74) * Fix LinkedList * Fix the prepend method for the LinkedList * Fix the remove method for the MinHeap * Correct a comment * Fix BST removal method --- .../binary-search-tree/BinarySearchTreeNode.js | 18 +++++++++++------- .../__test__/BinarySearchTreeNode.test.js | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js index 9ad74483da..06d99e431b 100644 --- a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js +++ b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js @@ -94,8 +94,13 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { if (!nodeToRemove.left && !nodeToRemove.right) { // Node is a leaf and thus has no children. - // Just remove the pointer to this node from the parent node. - parent.removeChild(nodeToRemove); + if (parent) { + // Node has a parent. Just remove the pointer to this node from the parent. + parent.removeChild(nodeToRemove); + } else { + // Node has no parent. Just erase current node value. + nodeToRemove.value = null; + } } else if (nodeToRemove.left && nodeToRemove.right) { // Node has two children. // Find the next biggest value (minimum value in the right branch) @@ -113,11 +118,10 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { } else { // Node has only one child. // Make this child to be a direct child of current node's parent. - if (nodeToRemove.left) { - parent.replaceChild(nodeToRemove, nodeToRemove.left); - } else { - parent.replaceChild(nodeToRemove, nodeToRemove.right); - } + const child = nodeToRemove.left || nodeToRemove.right; + nodeToRemove.value = child.value; + nodeToRemove.setLeft(child.left); + nodeToRemove.setRight(child.right); } return true; diff --git a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js index a353c1f1e1..63b9d999d6 100644 --- a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js +++ b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTreeNode.test.js @@ -185,6 +185,21 @@ describe('BinarySearchTreeNode', () => { expect(bstRootNode.toString()).toBe('30'); }); + it('should remove node with no parent', () => { + const bstRootNode = new BinarySearchTreeNode(); + expect(bstRootNode.toString()).toBe(''); + + bstRootNode.insert(1); + bstRootNode.insert(2); + expect(bstRootNode.toString()).toBe('1,2'); + + bstRootNode.remove(1); + expect(bstRootNode.toString()).toBe('2'); + + bstRootNode.remove(2); + expect(bstRootNode.toString()).toBe(''); + }); + it('should throw error when trying to remove not existing node', () => { const bstRootNode = new BinarySearchTreeNode(); From 2334583635308920d96cd3ad0689e928e88913b4 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 08:22:12 +0300 Subject: [PATCH 18/44] Add setValue and nodeCopy methods to binary tree node. --- src/data-structures/tree/BinaryTreeNode.js | 20 ++++++++++ .../tree/__test__/BinaryTreeNode.test.js | 37 +++++++++++++++++++ .../BinarySearchTreeNode.js | 20 ++++++---- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/data-structures/tree/BinaryTreeNode.js b/src/data-structures/tree/BinaryTreeNode.js index 9205e4820e..44c9390e41 100644 --- a/src/data-structures/tree/BinaryTreeNode.js +++ b/src/data-structures/tree/BinaryTreeNode.js @@ -85,6 +85,16 @@ export default class BinaryTreeNode { return this.parent.parent.left; } + /** + * @param {*} value + * @return {BinaryTreeNode} + */ + setValue(value) { + this.value = value; + + return this; + } + /** * @param {BinaryTreeNode} node * @return {BinaryTreeNode} @@ -168,6 +178,16 @@ export default class BinaryTreeNode { return false; } + /** + * @param {BinaryTreeNode} sourceNode + * @param {BinaryTreeNode} targetNode + */ + static copyNode(sourceNode, targetNode) { + targetNode.setValue(sourceNode.value); + targetNode.setLeft(sourceNode.left); + targetNode.setRight(sourceNode.right); + } + /** * @return {*[]} */ diff --git a/src/data-structures/tree/__test__/BinaryTreeNode.test.js b/src/data-structures/tree/__test__/BinaryTreeNode.test.js index 5a38329614..bc2336e12f 100644 --- a/src/data-structures/tree/__test__/BinaryTreeNode.test.js +++ b/src/data-structures/tree/__test__/BinaryTreeNode.test.js @@ -257,4 +257,41 @@ describe('BinaryTreeNode', () => { expect(child.uncle).toBeDefined(); expect(child.uncle).toEqual(uncle); }); + + it('should be possible to set node values', () => { + const node = new BinaryTreeNode('initial_value'); + + expect(node.value).toBe('initial_value'); + + node.setValue('new_value'); + + expect(node.value).toBe('new_value'); + }); + + it('should be possible to copy node', () => { + const root = new BinaryTreeNode('root'); + const left = new BinaryTreeNode('left'); + const right = new BinaryTreeNode('right'); + + root + .setLeft(left) + .setRight(right); + + expect(root.toString()).toBe('left,root,right'); + + const newRoot = new BinaryTreeNode('new_root'); + const newLeft = new BinaryTreeNode('new_left'); + const newRight = new BinaryTreeNode('new_right'); + + newRoot + .setLeft(newLeft) + .setRight(newRight); + + expect(newRoot.toString()).toBe('new_left,new_root,new_right'); + + BinaryTreeNode.copyNode(root, newRoot); + + expect(root.toString()).toBe('left,root,right'); + expect(newRoot.toString()).toBe('left,root,right'); + }); }); diff --git a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js index 06d99e431b..36126a9c1f 100644 --- a/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js +++ b/src/data-structures/tree/binary-search-tree/BinarySearchTreeNode.js @@ -99,7 +99,7 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { parent.removeChild(nodeToRemove); } else { // Node has no parent. Just erase current node value. - nodeToRemove.value = null; + nodeToRemove.setValue(undefined); } } else if (nodeToRemove.left && nodeToRemove.right) { // Node has two children. @@ -108,20 +108,24 @@ export default class BinarySearchTreeNode extends BinaryTreeNode { const nextBiggerNode = nodeToRemove.right.findMin(); if (!this.nodeComparator.equal(nextBiggerNode, nodeToRemove.right)) { this.remove(nextBiggerNode.value); - nodeToRemove.value = nextBiggerNode.value; + nodeToRemove.setValue(nextBiggerNode.value); } else { // In case if next right value is the next bigger one and it doesn't have left child // then just replace node that is going to be deleted with the right node. - nodeToRemove.value = nodeToRemove.right.value; - nodeToRemove.right = nodeToRemove.right.right; + nodeToRemove.setValue(nodeToRemove.right.value); + nodeToRemove.setRight(nodeToRemove.right.right); } } else { // Node has only one child. // Make this child to be a direct child of current node's parent. - const child = nodeToRemove.left || nodeToRemove.right; - nodeToRemove.value = child.value; - nodeToRemove.setLeft(child.left); - nodeToRemove.setRight(child.right); + /** @var BinarySearchTreeNode */ + const childNode = nodeToRemove.left || nodeToRemove.right; + + if (parent) { + parent.replaceChild(nodeToRemove, childNode); + } else { + BinaryTreeNode.copyNode(childNode, nodeToRemove); + } } return true; From 16b6ea506a8f9d8d1a31dacdd964d3f348053a91 Mon Sep 17 00:00:00 2001 From: Nnadozie Okeke Date: Fri, 22 Jun 2018 12:31:57 +0100 Subject: [PATCH 19/44] Corrected explanations and included an example (#75) --- .../integer-partition/integerPartition.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/algorithms/math/integer-partition/integerPartition.js b/src/algorithms/math/integer-partition/integerPartition.js index 283d9a400e..d2658d4cf3 100644 --- a/src/algorithms/math/integer-partition/integerPartition.js +++ b/src/algorithms/math/integer-partition/integerPartition.js @@ -17,9 +17,10 @@ export default function integerPartition(number) { partitionMatrix[0][numberIndex] = 0; } - // Let's fill the first row. It represents the number of way of how we can form - // number zero out of numbers 0, 1, 2, ... Obviously there is only one way we could - // form number 0 and it is with number 0 itself. + // Let's fill the first column. It represents the number of ways we can form + // number zero out of numbers 0, 0 and 1, 0 and 1 and 2, 0 and 1 and 2 and 3, ... + // Obviously there is only one way we could form number 0 + // and it is with number 0 itself. for (let summandIndex = 0; summandIndex <= number; summandIndex += 1) { partitionMatrix[summandIndex][0] = 1; } @@ -35,7 +36,18 @@ export default function integerPartition(number) { } else { // The number of combinations would equal to number of combinations of forming the same // number but WITHOUT current summand number plus number of combinations of forming the - // previous number but WITH current summand. + // number but WITH current summand. + // Example: number of ways to form number 4 using summands 1, 2 and 3 is the sum of + // {number of ways to form 4 with sums that begin with 1 + + // number of ways to form 4 with sums that begin with 2 and include 1} + + // {number of ways to form 4 with sums that begin with 3 and include 2 and 1} + // Taking these sums to proceed in descending order of intergers, this gives us: + // With 1: 1+1+1+1 -> 1 way + // With 2: 2+2, 2+1+1 -> 2 ways + // With 3: 3 + (4-3) <= convince yourself that number of ways to form 4 starting + // with 3 is == number of ways to form 4-3 where 4-3 == + // Helper: if there are n ways to get (4-3) then 4 can be represented as 3 + first way, + // 3 + second way, and so on until the 3 + nth way. So answer for 4 is: 1 + 2 + 1 = 4 ways const combosWithoutSummand = partitionMatrix[summandIndex - 1][numberIndex]; const combosWithSummand = partitionMatrix[summandIndex][numberIndex - summandIndex]; From 831ce89a454301193eacd8500aa80c962591a061 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 14:50:38 +0300 Subject: [PATCH 20/44] Update README for integer partition. --- .../integer-partition/integerPartition.js | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/algorithms/math/integer-partition/integerPartition.js b/src/algorithms/math/integer-partition/integerPartition.js index d2658d4cf3..02cb31f69f 100644 --- a/src/algorithms/math/integer-partition/integerPartition.js +++ b/src/algorithms/math/integer-partition/integerPartition.js @@ -34,20 +34,17 @@ export default function integerPartition(number) { // any new ways of forming the number. Thus we may just copy the number from row above. partitionMatrix[summandIndex][numberIndex] = partitionMatrix[summandIndex - 1][numberIndex]; } else { - // The number of combinations would equal to number of combinations of forming the same - // number but WITHOUT current summand number plus number of combinations of forming the - // number but WITH current summand. - // Example: number of ways to form number 4 using summands 1, 2 and 3 is the sum of - // {number of ways to form 4 with sums that begin with 1 + - // number of ways to form 4 with sums that begin with 2 and include 1} + - // {number of ways to form 4 with sums that begin with 3 and include 2 and 1} - // Taking these sums to proceed in descending order of intergers, this gives us: - // With 1: 1+1+1+1 -> 1 way - // With 2: 2+2, 2+1+1 -> 2 ways - // With 3: 3 + (4-3) <= convince yourself that number of ways to form 4 starting - // with 3 is == number of ways to form 4-3 where 4-3 == - // Helper: if there are n ways to get (4-3) then 4 can be represented as 3 + first way, - // 3 + second way, and so on until the 3 + nth way. So answer for 4 is: 1 + 2 + 1 = 4 ways + /* + * The number of combinations would equal to number of combinations of forming the same + * number but WITHOUT current summand number PLUS number of combinations of forming the + * number but WITH current summand. + * + * Example: + * Number of ways to form 5 using summands {0, 1, 2} would equal the SUM of: + * - number of ways to form 5 using summands {0, 1} (we've excluded summand 2) + * - number of ways to form 3 (because 5 - 2 = 3) using summands {0, 1, 2} + * (we've included summand 2) + */ const combosWithoutSummand = partitionMatrix[summandIndex - 1][numberIndex]; const combosWithSummand = partitionMatrix[summandIndex][numberIndex - summandIndex]; From e53f5f909dd3c4b1ca5cc960d6533e010efa877c Mon Sep 17 00:00:00 2001 From: Amjad Ali Date: Fri, 22 Jun 2018 06:54:40 -0500 Subject: [PATCH 21/44] Added Complexity of Each Algorithm in Sorting/ directory. (#76) * Added Complexity to Bubble Sort README.md * Added Complexity to Counting-Sort README.md * Italicized n in Bubble Sort README.md * Added Complexity to Heap Sort README.md * Added Complexity to Insertion Sort README.md * Added Complexity to Merge Sort README.md * Added Complexity to Quick Sort README.md * Added Complexity to Radix Sort README.md * Added Complexity to Selection Sort README.md * Added Complexity to SHell Sort README.md --- src/algorithms/sorting/bubble-sort/README.md | 7 +++++++ src/algorithms/sorting/counting-sort/README.md | 6 ++++++ src/algorithms/sorting/heap-sort/README.md | 6 ++++++ src/algorithms/sorting/insertion-sort/README.md | 7 +++++++ src/algorithms/sorting/merge-sort/README.md | 6 ++++++ src/algorithms/sorting/quick-sort/README.md | 6 ++++++ src/algorithms/sorting/radix-sort/README.md | 6 ++++++ src/algorithms/sorting/selection-sort/README.md | 6 ++++++ src/algorithms/sorting/shell-sort/README.md | 6 ++++++ 9 files changed, 56 insertions(+) diff --git a/src/algorithms/sorting/bubble-sort/README.md b/src/algorithms/sorting/bubble-sort/README.md index 4861dc2e41..8d3c64d40a 100644 --- a/src/algorithms/sorting/bubble-sort/README.md +++ b/src/algorithms/sorting/bubble-sort/README.md @@ -9,6 +9,13 @@ are needed, which indicates that the list is sorted. ![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/c/c8/Bubble-sort-example-300px.gif) +## Complexity + +###### time: worst _O_(_n_2), best _O_(_n_), average _O_(_n_2) + +###### space: worst _O_(1) auxiliary + + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Bubble_sort) diff --git a/src/algorithms/sorting/counting-sort/README.md b/src/algorithms/sorting/counting-sort/README.md index 261efe521a..d210f32d4f 100644 --- a/src/algorithms/sorting/counting-sort/README.md +++ b/src/algorithms/sorting/counting-sort/README.md @@ -54,6 +54,12 @@ zero. ![Counting Sort](https://1.bp.blogspot.com/-xPqylngqASY/WLGq3p9n9vI/AAAAAAAAAHM/JHdtXAkJY8wYzDMBXxqarjmhpPhM0u8MACLcB/s1600/ResultArrayCS.gif) +## Complexity + +###### time: worst _O_(_n_ + _k_), best _O_(_n_), average _O_(_n_ + _k_) where _n_ is the number of elements in the input array and _k_ is the range of the output. + +###### space: worst _O_(_n_ + _k_) + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Counting_sort) diff --git a/src/algorithms/sorting/heap-sort/README.md b/src/algorithms/sorting/heap-sort/README.md index 7504875dfa..9c402d566c 100644 --- a/src/algorithms/sorting/heap-sort/README.md +++ b/src/algorithms/sorting/heap-sort/README.md @@ -13,6 +13,12 @@ rather than a linear-time search to find the maximum. ![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/4/4d/Heapsort-example.gif) +## Complexity + +###### time: worst _O_(_n log n_), best _O_(_n log n_), average _O_(_n log n_) + +###### space: worst _O_(1) auxiliary + ## References [Wikipedia](https://en.wikipedia.org/wiki/Heapsort) diff --git a/src/algorithms/sorting/insertion-sort/README.md b/src/algorithms/sorting/insertion-sort/README.md index a31804d4f3..3f59f5ab45 100644 --- a/src/algorithms/sorting/insertion-sort/README.md +++ b/src/algorithms/sorting/insertion-sort/README.md @@ -10,6 +10,13 @@ sort. ![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif) +## Complexity + +###### time: worst _O_(_n_2), best _O_(_n_), average _O_(_n_2) + +###### space: worst _O_(1) auxiliary + + ## References [Wikipedia](https://en.wikipedia.org/wiki/Insertion_sort) diff --git a/src/algorithms/sorting/merge-sort/README.md b/src/algorithms/sorting/merge-sort/README.md index 372cc2ac6b..e015b05808 100644 --- a/src/algorithms/sorting/merge-sort/README.md +++ b/src/algorithms/sorting/merge-sort/README.md @@ -22,6 +22,12 @@ emulate merge sort (top-down). ![Merge Sort](https://upload.wikimedia.org/wikipedia/commons/e/e6/Merge_sort_algorithm_diagram.svg) +## Complexity + +###### time: average _O_(_n log n_) + +###### space: worst _O_(_n_) + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Merge_sort) diff --git a/src/algorithms/sorting/quick-sort/README.md b/src/algorithms/sorting/quick-sort/README.md index 3021e6e2da..50b6393116 100644 --- a/src/algorithms/sorting/quick-sort/README.md +++ b/src/algorithms/sorting/quick-sort/README.md @@ -23,6 +23,12 @@ The horizontal lines are pivot values. ![Quicksort](https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif) +## Complexity + +###### time: worst _O_(_n_2), best _O_(_n log n_), average _O_(_n log n_) + +###### space: worst _O_(_n_) auxiliary + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Quicksort) diff --git a/src/algorithms/sorting/radix-sort/README.md b/src/algorithms/sorting/radix-sort/README.md index 01471cb3fa..90920fe300 100644 --- a/src/algorithms/sorting/radix-sort/README.md +++ b/src/algorithms/sorting/radix-sort/README.md @@ -25,6 +25,12 @@ comparison-based sorts (and worse if keys are much longer than `log n`). ![Radix Sort](https://www.researchgate.net/publication/291086231/figure/fig1/AS:614214452404240@1523451545568/Simplistic-illustration-of-the-steps-performed-in-a-radix-sort-In-this-example-the.png) +## Complexity + +###### time: worst _O_(_n_), best _O_(_n_), average _O_(_n_) + +###### space: always _O_(_n_) + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Radix_sort) diff --git a/src/algorithms/sorting/selection-sort/README.md b/src/algorithms/sorting/selection-sort/README.md index 7a16f205ea..cc1fbeec0a 100644 --- a/src/algorithms/sorting/selection-sort/README.md +++ b/src/algorithms/sorting/selection-sort/README.md @@ -13,6 +13,12 @@ memory is limited. ![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/9/94/Selection-Sort-Animation.gif) +## Complexity + +###### time: worst _O_(_n_2), best _O_(_n_2), average _O_(_n_2) + +###### space: _O_(1) auxiliary + ## References [Wikipedia](https://en.wikipedia.org/wiki/Selection_sort) diff --git a/src/algorithms/sorting/shell-sort/README.md b/src/algorithms/sorting/shell-sort/README.md index 9d202c55e9..3837ecbc23 100644 --- a/src/algorithms/sorting/shell-sort/README.md +++ b/src/algorithms/sorting/shell-sort/README.md @@ -42,6 +42,12 @@ Shell sort uses insertion sort to sort the array. ![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort.jpg) +## Complexity + +###### time: best _O_(_n log n_), average - depends on 'gap sequence'. + +###### space: worst _O_(_n_) total, _O_(1) auxiliary + ## References * [Tutorials Point](https://www.tutorialspoint.com/data_structures_algorithms/shell_sort_algorithm.htm) From b65a992452f4062aaf03ad30b9005a442636471f Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:04:28 +0300 Subject: [PATCH 22/44] Update READMEs. --- README.md | 44 ++++++++++---------- src/algorithms/sorting/bubble-sort/README.md | 10 ++++- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 690c80ab08..077362e732 100644 --- a/README.md +++ b/README.md @@ -215,28 +215,28 @@ Below is the list of some of the most used Big O notations and their performance ### Data Structure Operations Complexity -| Data Structure | Access | Search | Insertion | Deletion | Comments | -| ----------------------- | :-------: | :-------: | :-------: | :-------: | :-------- | -| **Array** | 1 | n | n | n | | -| **Stack** | n | n | 1 | 1 | | -| **Queue** | n | n | 1 | 1 | | -| **Linked List** | n | n | 1 | 1 | | -| **Hash Table** | - | n | n | n | In case of perfect hash function costs would be O(1) | -| **Binary Search Tree** | n | n | n | n | In case of balanced tree costs would be O(log(n)) | -| **B-Tree** | log(n) | log(n) | log(n) | log(n) | | -| **Red-Black Tree** | log(n) | log(n) | log(n) | log(n) | | -| **AVL Tree** | log(n) | log(n) | log(n) | log(n) | | +| Data Structure | Access | Search | Insertion | Deletion | Comments | +| ----------------------- | :---------: | :---------: | :---------: | :---------: | :-------- | +| **Array** | `1` | `n` | `n` | `n` | | +| **Stack** | `n` | `n` | `1` | `1` | | +| **Queue** | `n` | `n` | `1` | `1` | | +| **Linked List** | `n` | `n` | `1` | `1` | | +| **Hash Table** | - | `n` | `n` | `n` | In case of perfect hash function costs would be `O(1)` | +| **Binary Search Tree** | `n` | `n` | `n` | `n` | In case of balanced tree costs would be `O(log(n))` | +| **B-Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | +| **Red-Black Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | +| **AVL Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | ### Array Sorting Algorithms Complexity -| Name | Best | Average | Worst | Memory | Stable | Comments | -| --------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: | :-------- | -| **Bubble sort** | n | n^2 | n^2 | 1 | Yes | | -| **Insertion sort** | n | n^2 | n^2 | 1 | Yes | | -| **Selection sort** | n^2 | n^2 | n^2 | 1 | No | | -| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | -| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | -| **Quick sort** | n log(n) | n log(n) | n^2 | log(n) | No | | -| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))^2 | 1 | No | | -| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | -| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :---------: | :---------: | :-------------: | :---------: | :-------: | :-------- | +| **Bubble sort** | `n` | `n^2` | `n^2` | `1` | Yes | | +| **Insertion sort** | `n ` | `n^2` | `n^2` | `1` | Yes | | +| **Selection sort** | `n^2` | `n^2` | `n^2` | `1` | No | | +| **Heap sort** | `n log(n)` | `n log(n)` | `n log(n)` | `1` | No | | +| **Merge sort** | `n log(n)` | `n log(n)` | `n log(n)` | `n` | Yes | | +| **Quick sort** | `n log(n)` | `n log(n)` | `n^2` | `log(n)` | No | | +| **Shell sort** | `n log(n)` | depends on gap sequence | `n (log(n))^2` | `1` | No | | +| **Counting sort** | `n + r` | `n + r` | `n + r` | `n + r` | Yes | `r` - biggest number in array | +| **Radix sort** | `n * k` | `n * k` | `n * k` | `n + k` | Yes | `k` - length of longest key | diff --git a/src/algorithms/sorting/bubble-sort/README.md b/src/algorithms/sorting/bubble-sort/README.md index 8d3c64d40a..43610be763 100644 --- a/src/algorithms/sorting/bubble-sort/README.md +++ b/src/algorithms/sorting/bubble-sort/README.md @@ -11,9 +11,15 @@ are needed, which indicates that the list is sorted. ## Complexity -###### time: worst _O_(_n_2), best _O_(_n_), average _O_(_n_2) +Time -###### space: worst _O_(1) auxiliary +- worst _O_(_n_2), +- best _O_(_n_), +- average _O_(_n_2) + +Space + +worst _O_(1) auxiliary ## References From 413c134683605730e6464f2a7710799931673e2b Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:11:34 +0300 Subject: [PATCH 23/44] Update READMEs. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 077362e732..a70d92081f 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ Below is the list of some of the most used Big O notations and their performance | **Selection sort** | `n^2` | `n^2` | `n^2` | `1` | No | | | **Heap sort** | `n log(n)` | `n log(n)` | `n log(n)` | `1` | No | | | **Merge sort** | `n log(n)` | `n log(n)` | `n log(n)` | `n` | Yes | | -| **Quick sort** | `n log(n)` | `n log(n)` | `n^2` | `log(n)` | No | | -| **Shell sort** | `n log(n)` | depends on gap sequence | `n (log(n))^2` | `1` | No | | +| **Quick sort** | `n log(n)` | `n log(n)` | `n``2` | `log(n)` | No | | +| **Shell sort** | `n log(n)` | depends on gap sequence | `n (log(n))``2` | `1` | No | | | **Counting sort** | `n + r` | `n + r` | `n + r` | `n + r` | Yes | `r` - biggest number in array | | **Radix sort** | `n * k` | `n * k` | `n * k` | `n + k` | Yes | `k` - length of longest key | From 110cc01e158623d6121650b7c6025c006ba20a21 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:15:54 +0300 Subject: [PATCH 24/44] Update READMEs. --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index a70d92081f..e986fab7b6 100644 --- a/README.md +++ b/README.md @@ -215,28 +215,28 @@ Below is the list of some of the most used Big O notations and their performance ### Data Structure Operations Complexity -| Data Structure | Access | Search | Insertion | Deletion | Comments | -| ----------------------- | :---------: | :---------: | :---------: | :---------: | :-------- | -| **Array** | `1` | `n` | `n` | `n` | | -| **Stack** | `n` | `n` | `1` | `1` | | -| **Queue** | `n` | `n` | `1` | `1` | | -| **Linked List** | `n` | `n` | `1` | `1` | | -| **Hash Table** | - | `n` | `n` | `n` | In case of perfect hash function costs would be `O(1)` | -| **Binary Search Tree** | `n` | `n` | `n` | `n` | In case of balanced tree costs would be `O(log(n))` | -| **B-Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | -| **Red-Black Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | -| **AVL Tree** | `log(n)` | `log(n)` | `log(n)` | `log(n)` | | +| Data Structure | Access | Search | Insertion | Deletion | Comments | +| ----------------------- | :-------: | :-------: | :-------: | :-------: | :-------- | +| **Array** | 1 | n | n | n | | +| **Stack** | n | n | 1 | 1 | | +| **Queue** | n | n | 1 | 1 | | +| **Linked List** | n | n | 1 | 1 | | +| **Hash Table** | - | n | n | n | In case of perfect hash function costs would be O(1) | +| **Binary Search Tree** | n | n | n | n | In case of balanced tree costs would be O(log(n)) | +| **B-Tree** | log(n) | log(n) | log(n) | log(n) | | +| **Red-Black Tree** | log(n) | log(n) | log(n) | log(n) | | +| **AVL Tree** | log(n) | log(n) | log(n) | log(n) | | ### Array Sorting Algorithms Complexity -| Name | Best | Average | Worst | Memory | Stable | Comments | -| --------------------- | :---------: | :---------: | :-------------: | :---------: | :-------: | :-------- | -| **Bubble sort** | `n` | `n^2` | `n^2` | `1` | Yes | | -| **Insertion sort** | `n ` | `n^2` | `n^2` | `1` | Yes | | -| **Selection sort** | `n^2` | `n^2` | `n^2` | `1` | No | | -| **Heap sort** | `n log(n)` | `n log(n)` | `n log(n)` | `1` | No | | -| **Merge sort** | `n log(n)` | `n log(n)` | `n log(n)` | `n` | Yes | | -| **Quick sort** | `n log(n)` | `n log(n)` | `n``2` | `log(n)` | No | | -| **Shell sort** | `n log(n)` | depends on gap sequence | `n (log(n))``2` | `1` | No | | -| **Counting sort** | `n + r` | `n + r` | `n + r` | `n + r` | Yes | `r` - biggest number in array | -| **Radix sort** | `n * k` | `n * k` | `n * k` | `n + k` | Yes | `k` - length of longest key | +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: | :-------- | +| **Bubble sort** | n | n2 | n2 | 1 | Yes | | +| **Insertion sort** | n | n2 | n2 | 1 | Yes | | +| **Selection sort** | n2 | n2 | n2 | 1 | No | | +| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | +| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | +| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | +| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | +| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | +| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | From 3123cef25486fc573ee847f8f72b100a4d374d87 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:19:42 +0300 Subject: [PATCH 25/44] Update READMEs. --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e986fab7b6..88d0b3898a 100644 --- a/README.md +++ b/README.md @@ -229,14 +229,14 @@ Below is the list of some of the most used Big O notations and their performance ### Array Sorting Algorithms Complexity -| Name | Best | Average | Worst | Memory | Stable | Comments | -| --------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: | :-------- | -| **Bubble sort** | n | n2 | n2 | 1 | Yes | | -| **Insertion sort** | n | n2 | n2 | 1 | Yes | | -| **Selection sort** | n2 | n2 | n2 | 1 | No | | -| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | -| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | -| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | -| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | -| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | -| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Bubble sort** | n | n2 | n2 | 1 | Yes | | +| **Insertion sort** | n | n2 | n2 | 1 | Yes | | +| **Selection sort** | n2 | n2 | n2 | 1 | No | | +| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | +| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | +| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | +| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | +| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | +| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | From 5ac8bc98e704b9a5183ade2c81330747c0747711 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:24:25 +0300 Subject: [PATCH 26/44] Update READMEs. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 88d0b3898a..85e22cf513 100644 --- a/README.md +++ b/README.md @@ -234,9 +234,9 @@ Below is the list of some of the most used Big O notations and their performance | **Bubble sort** | n | n2 | n2 | 1 | Yes | | | **Insertion sort** | n | n2 | n2 | 1 | Yes | | | **Selection sort** | n2 | n2 | n2 | 1 | No | | -| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | -| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | -| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | -| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | +| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | +| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | +| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | +| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | | **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | | **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | From 619c58ec87475aa166331b307aceaf57d7c3e08f Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:34:32 +0300 Subject: [PATCH 27/44] Update READMEs. --- src/algorithms/sorting/bubble-sort/README.md | 13 +++---------- src/algorithms/sorting/counting-sort/README.md | 6 +++--- src/algorithms/sorting/heap-sort/README.md | 6 +++--- src/algorithms/sorting/insertion-sort/README.md | 7 +++---- src/algorithms/sorting/merge-sort/README.md | 6 +++--- src/algorithms/sorting/quick-sort/README.md | 6 +++--- src/algorithms/sorting/radix-sort/README.md | 6 +++--- src/algorithms/sorting/selection-sort/README.md | 6 +++--- src/algorithms/sorting/shell-sort/README.md | 6 +++--- 9 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/algorithms/sorting/bubble-sort/README.md b/src/algorithms/sorting/bubble-sort/README.md index 43610be763..aed7169615 100644 --- a/src/algorithms/sorting/bubble-sort/README.md +++ b/src/algorithms/sorting/bubble-sort/README.md @@ -11,16 +11,9 @@ are needed, which indicates that the list is sorted. ## Complexity -Time - -- worst _O_(_n_2), -- best _O_(_n_), -- average _O_(_n_2) - -Space - -worst _O_(1) auxiliary - +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Bubble sort** | n | n2 | n2 | 1 | Yes | | ## References diff --git a/src/algorithms/sorting/counting-sort/README.md b/src/algorithms/sorting/counting-sort/README.md index d210f32d4f..098961a0e0 100644 --- a/src/algorithms/sorting/counting-sort/README.md +++ b/src/algorithms/sorting/counting-sort/README.md @@ -56,9 +56,9 @@ zero. ## Complexity -###### time: worst _O_(_n_ + _k_), best _O_(_n_), average _O_(_n_ + _k_) where _n_ is the number of elements in the input array and _k_ is the range of the output. - -###### space: worst _O_(_n_ + _k_) +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - biggest number in array | ## References diff --git a/src/algorithms/sorting/heap-sort/README.md b/src/algorithms/sorting/heap-sort/README.md index 9c402d566c..6ccc50b3b0 100644 --- a/src/algorithms/sorting/heap-sort/README.md +++ b/src/algorithms/sorting/heap-sort/README.md @@ -15,9 +15,9 @@ rather than a linear-time search to find the maximum. ## Complexity -###### time: worst _O_(_n log n_), best _O_(_n log n_), average _O_(_n log n_) - -###### space: worst _O_(1) auxiliary +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No | | ## References diff --git a/src/algorithms/sorting/insertion-sort/README.md b/src/algorithms/sorting/insertion-sort/README.md index 3f59f5ab45..cd3a74ef34 100644 --- a/src/algorithms/sorting/insertion-sort/README.md +++ b/src/algorithms/sorting/insertion-sort/README.md @@ -12,10 +12,9 @@ sort. ## Complexity -###### time: worst _O_(_n_2), best _O_(_n_), average _O_(_n_2) - -###### space: worst _O_(1) auxiliary - +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Insertion sort** | n | n2 | n2 | 1 | Yes | | ## References diff --git a/src/algorithms/sorting/merge-sort/README.md b/src/algorithms/sorting/merge-sort/README.md index e015b05808..f4ed837a22 100644 --- a/src/algorithms/sorting/merge-sort/README.md +++ b/src/algorithms/sorting/merge-sort/README.md @@ -24,9 +24,9 @@ emulate merge sort (top-down). ## Complexity -###### time: average _O_(_n log n_) - -###### space: worst _O_(_n_) +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes | | ## References diff --git a/src/algorithms/sorting/quick-sort/README.md b/src/algorithms/sorting/quick-sort/README.md index 50b6393116..683a7f3f71 100644 --- a/src/algorithms/sorting/quick-sort/README.md +++ b/src/algorithms/sorting/quick-sort/README.md @@ -25,9 +25,9 @@ The horizontal lines are pivot values. ## Complexity -###### time: worst _O_(_n_2), best _O_(_n log n_), average _O_(_n log n_) - -###### space: worst _O_(_n_) auxiliary +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Quick sort** | n log(n) | n log(n) | n2 | log(n) | No | | ## References diff --git a/src/algorithms/sorting/radix-sort/README.md b/src/algorithms/sorting/radix-sort/README.md index 90920fe300..1d1fab1852 100644 --- a/src/algorithms/sorting/radix-sort/README.md +++ b/src/algorithms/sorting/radix-sort/README.md @@ -27,9 +27,9 @@ comparison-based sorts (and worse if keys are much longer than `log n`). ## Complexity -###### time: worst _O_(_n_), best _O_(_n_), average _O_(_n_) - -###### space: always _O_(_n_) +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - length of longest key | ## References diff --git a/src/algorithms/sorting/selection-sort/README.md b/src/algorithms/sorting/selection-sort/README.md index cc1fbeec0a..6a708d2579 100644 --- a/src/algorithms/sorting/selection-sort/README.md +++ b/src/algorithms/sorting/selection-sort/README.md @@ -15,9 +15,9 @@ memory is limited. ## Complexity -###### time: worst _O_(_n_2), best _O_(_n_2), average _O_(_n_2) - -###### space: _O_(1) auxiliary +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Selection sort** | n2 | n2 | n2 | 1 | No | | ## References diff --git a/src/algorithms/sorting/shell-sort/README.md b/src/algorithms/sorting/shell-sort/README.md index 3837ecbc23..5030333f79 100644 --- a/src/algorithms/sorting/shell-sort/README.md +++ b/src/algorithms/sorting/shell-sort/README.md @@ -44,9 +44,9 @@ Shell sort uses insertion sort to sort the array. ## Complexity -###### time: best _O_(_n log n_), average - depends on 'gap sequence'. - -###### space: worst _O_(_n_) total, _O_(1) auxiliary +| Name | Best | Average | Worst | Memory | Stable | Comments | +| --------------------- | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- | +| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))2 | 1 | No | | ## References From 6b67ca75a51bd7e0fb2852c43508d2c40e4b08cd Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:38:18 +0300 Subject: [PATCH 28/44] Update READMEs. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 85e22cf513..a114106905 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ a set of rules that precisely define a sequence of operations. * `B` [Linear Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/linear-search) * `B` [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) * **Sorting** - * `B` [Bubble Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort) - * `B` [Selection Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort) + * `B` [Bubble Sort](src/algorithms/sorting/bubble-sort) + * `B` [Selection Sort](src/algorithms/sorting/selection-sort) * `B` [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) * `B` [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) * `B` [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) From 571d0362c0fc384a7e42675bb7f39de18babfb03 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:41:35 +0300 Subject: [PATCH 29/44] Update READMEs. --- README.md | 196 +++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index a114106905..7246abc1e5 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ with related explanations and links for further reading (including ones to YouTube videos). _Read this in other languages:_ -[简体中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-CN.md), -[繁體中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-TW.md) +[简体中文](README.zh-CN.md), +[繁體中文](README.zh-TW.md) ## Data Structures @@ -23,21 +23,21 @@ the data. `B` - Beginner, `A` - Advanced -* `B` [Linked List](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list) -* `B` [Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue) -* `B` [Stack](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) -* `B` [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) -* `B` [Heap](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) -* `B` [Priority Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) -* `A` [Trie](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) -* `A` [Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) - * `A` [Binary Search Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) - * `A` [AVL Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) - * `A` [Red-Black Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/red-black-tree) - * `A` [Segment Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/segment-tree) - with min/max/sum range queries examples - * `A` [Fenwick Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/fenwick-tree) (Binary Indexed Tree) -* `A` [Graph](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/graph) (both directed and undirected) -* `A` [Disjoint Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/disjoint-set) +* `B` [Linked List](src/data-structures/linked-list) +* `B` [Queue](src/data-structures/queue) +* `B` [Stack](src/data-structures/stack) +* `B` [Hash Table](src/data-structures/hash-table) +* `B` [Heap](src/data-structures/heap) +* `B` [Priority Queue](src/data-structures/priority-queue) +* `A` [Trie](src/data-structures/trie) +* `A` [Tree](src/data-structures/tree) + * `A` [Binary Search Tree](src/data-structures/tree/binary-search-tree) + * `A` [AVL Tree](src/data-structures/tree/avl-tree) + * `A` [Red-Black Tree](src/data-structures/tree/red-black-tree) + * `A` [Segment Tree](src/data-structures/tree/segment-tree) - with min/max/sum range queries examples + * `A` [Fenwick Tree](src/data-structures/tree/fenwick-tree) (Binary Indexed Tree) +* `A` [Graph](src/data-structures/graph) (both directed and undirected) +* `A` [Disjoint Set](src/data-structures/disjoint-set) ## Algorithms @@ -49,68 +49,68 @@ a set of rules that precisely define a sequence of operations. ### Algorithms by Topic * **Math** - * `B` [Factorial](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial) - * `B` [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * `B` [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (trial division method) - * `B` [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) - * `B` [Least Common Multiple](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM) - * `A` [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * `B` [Sieve of Eratosthenes](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit - * `B` [Is Power of Two](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms) - * `A` [Liu Hui π Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/liu-hui) - approximate π calculations based on N-gons + * `B` [Factorial](src/algorithms/math/factorial) + * `B` [Fibonacci Number](src/algorithms/math/fibonacci) + * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) + * `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * `B` [Least Common Multiple](src/algorithms/math/least-common-multiple) (LCM) + * `A` [Integer Partition](src/algorithms/math/integer-partition) + * `B` [Sieve of Eratosthenes](src/algorithms/math/sieve-of-eratosthenes) - finding all prime numbers up to any given limit + * `B` [Is Power of Two](src/algorithms/math/is-power-of-two) - check if the number is power of two (naive and bitwise algorithms) + * `A` [Liu Hui π Algorithm](src/algorithms/math/liu-hui) - approximate π calculations based on N-gons * **Sets** - * `B` [Cartesian Product](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - product of multiple sets - * `A` [Power Set](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - all subsets of a set - * `A` [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) - * `A` [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) - * `B` [Fisher–Yates Shuffle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - random permutation of a finite sequence - * `A` [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence) (LCS) - * `A` [Longest Increasing Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * `A` [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS) - * `A` [Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones - * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" (Kadane's) versions + * `B` [Cartesian Product](src/algorithms/sets/cartesian-product) - product of multiple sets + * `A` [Power Set](src/algorithms/sets/power-set) - all subsets of a set + * `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions) + * `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions) + * `B` [Fisher–Yates Shuffle](src/algorithms/sets/fisher-yates) - random permutation of a finite sequence + * `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS) + * `A` [Longest Increasing Subsequence](src/algorithms/sets/longest-increasing-subsequence) + * `A` [Shortest Common Supersequence](src/algorithms/sets/shortest-common-supersequence) (SCS) + * `A` [Knapsack Problem](src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones + * `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray) - "Brute Force" and "Dynamic Programming" (Kadane's) versions * **Strings** - * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences - * `B` [Hamming Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different - * `A` [Knuth–Morris–Pratt Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) (KMP Algorithm) - substring search (pattern matching) - * `A` [Z Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/z-algorithm) - substring search (pattern matching) - * `A` [Rabin Karp Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - substring search - * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) + * `A` [Levenshtein Distance](src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences + * `B` [Hamming Distance](src/algorithms/string/hamming-distance) - number of positions at which the symbols are different + * `A` [Knuth–Morris–Pratt Algorithm](src/algorithms/string/knuth-morris-pratt) (KMP Algorithm) - substring search (pattern matching) + * `A` [Z Algorithm](src/algorithms/string/z-algorithm) - substring search (pattern matching) + * `A` [Rabin Karp Algorithm](src/algorithms/string/rabin-karp) - substring search + * `A` [Longest Common Substring](src/algorithms/string/longest-common-substring) * **Searches** - * `B` [Linear Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/linear-search) - * `B` [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) + * `B` [Linear Search](src/algorithms/search/linear-search) + * `B` [Binary Search](src/algorithms/search/binary-search) * **Sorting** * `B` [Bubble Sort](src/algorithms/sorting/bubble-sort) * `B` [Selection Sort](src/algorithms/sorting/selection-sort) - * `B` [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) - * `B` [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) - * `B` [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * `B` [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - in-place and non-in-place implementations - * `B` [Shellsort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort) - * `A` [Counting Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/counting-sort) - * `A` [Radix Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/radix-sort) + * `B` [Insertion Sort](src/algorithms/sorting/insertion-sort) + * `B` [Heap Sort](src/algorithms/sorting/heap-sort) + * `B` [Merge Sort](src/algorithms/sorting/merge-sort) + * `B` [Quicksort](src/algorithms/sorting/quick-sort) - in-place and non-in-place implementations + * `B` [Shellsort](src/algorithms/sorting/shell-sort) + * `A` [Counting Sort](src/algorithms/sorting/counting-sort) + * `A` [Radix Sort](src/algorithms/sorting/radix-sort) * **Trees** - * `B` [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * `B` [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/breadth-first-search) (BFS) + * `B` [Depth-First Search](src/algorithms/tree/depth-first-search) (DFS) + * `B` [Breadth-First Search](src/algorithms/tree/breadth-first-search) (BFS) * **Graphs** - * `B` [Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) - * `B` [Breadth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/breadth-first-search) (BFS) - * `A` [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices - * `A` [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices - * `A` [Detect Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) - * `A` [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * `B` [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * `A` [Topological Sorting](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/topological-sorting) - DFS method - * `A` [Articulation Points](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) - * `A` [Bridges](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bridges) - DFS based algorithm - * `A` [Eulerian Path and Eulerian Circuit](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once - * `A` [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * `A` [Strongly Connected Components](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm - * `A` [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * `B` [Depth-First Search](src/algorithms/graph/depth-first-search) (DFS) + * `B` [Breadth-First Search](src/algorithms/graph/breadth-first-search) (BFS) + * `A` [Dijkstra Algorithm](src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices + * `A` [Bellman-Ford Algorithm](src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * `A` [Detect Cycle](src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) + * `A` [Prim’s Algorithm](src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `B` [Kruskal’s Algorithm](src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Topological Sorting](src/algorithms/graph/topological-sorting) - DFS method + * `A` [Articulation Points](src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) + * `A` [Bridges](src/algorithms/graph/bridges) - DFS based algorithm + * `A` [Eulerian Path and Eulerian Circuit](src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once + * `A` [Hamiltonian Cycle](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * `A` [Strongly Connected Components](src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm + * `A` [Travelling Salesman Problem](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **Uncategorized** - * `B` [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * `A` [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * `A` [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * `B` [Tower of Hanoi](src/algorithms/uncategorized/hanoi-tower) + * `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens) + * `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour) ### Algorithms by Paradigm @@ -119,40 +119,40 @@ of algorithms. It is an abstraction higher than the notion of an algorithm, just algorithm is an abstraction higher than a computer program. * **Brute Force** - look at all the possibilities and selects the best solution - * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * `A` [Travelling Salesman Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray) + * `A` [Travelling Salesman Problem](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **Greedy** - choose the best option at the current time, without any consideration for the future - * `A` [Unbound Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * `A` [Dijkstra Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices - * `A` [Prim’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * `A` [Kruskal’s Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Unbound Knapsack Problem](src/algorithms/sets/knapsack-problem) + * `A` [Dijkstra Algorithm](src/algorithms/graph/dijkstra) - finding shortest path to all graph vertices + * `A` [Prim’s Algorithm](src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * `A` [Kruskal’s Algorithm](src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph * **Divide and Conquer** - divide the problem into smaller parts and then solve those parts - * `B` [Binary Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) - * `B` [Tower of Hanoi](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * `B` [Euclidean Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) - * `A` [Permutations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (with and without repetitions) - * `A` [Combinations](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (with and without repetitions) - * `B` [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * `B` [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * `B` [Tree Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * `B` [Graph Depth-First Search](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) + * `B` [Binary Search](src/algorithms/search/binary-search) + * `B` [Tower of Hanoi](src/algorithms/uncategorized/hanoi-tower) + * `B` [Euclidean Algorithm](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * `A` [Permutations](src/algorithms/sets/permutations) (with and without repetitions) + * `A` [Combinations](src/algorithms/sets/combinations) (with and without repetitions) + * `B` [Merge Sort](src/algorithms/sorting/merge-sort) + * `B` [Quicksort](src/algorithms/sorting/quick-sort) + * `B` [Tree Depth-First Search](src/algorithms/tree/depth-first-search) (DFS) + * `B` [Graph Depth-First Search](src/algorithms/graph/depth-first-search) (DFS) * **Dynamic Programming** - build up a solution using previously found sub-solutions - * `B` [Fibonacci Number](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * `A` [Levenshtein Distance](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences - * `A` [Longest Common Subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS) - * `A` [Longest Common Substring](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) - * `A` [Longest Increasing subsequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * `A` [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) - * `A` [0/1 Knapsack Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * `A` [Integer Partition](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * `A` [Maximum Subarray](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * `A` [Bellman-Ford Algorithm](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * `B` [Fibonacci Number](src/algorithms/math/fibonacci) + * `A` [Levenshtein Distance](src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences + * `A` [Longest Common Subsequence](src/algorithms/sets/longest-common-subsequence) (LCS) + * `A` [Longest Common Substring](src/algorithms/string/longest-common-substring) + * `A` [Longest Increasing subsequence](src/algorithms/sets/longest-increasing-subsequence) + * `A` [Shortest Common Supersequence](src/algorithms/sets/shortest-common-supersequence) + * `A` [0/1 Knapsack Problem](src/algorithms/sets/knapsack-problem) + * `A` [Integer Partition](src/algorithms/math/integer-partition) + * `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray) + * `A` [Bellman-Ford Algorithm](src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices * **Backtracking** - similarly to brute force, try to generate all possible solutions, but each time you generate next solution you test if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a different path of finding a solution. Normally the DFS traversal of state-space is being used. - * `A` [Hamiltonian Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * `A` [N-Queens Problem](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * `A` [Knight's Tour](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * `A` [Hamiltonian Cycle](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * `A` [N-Queens Problem](src/algorithms/uncategorized/n-queens) + * `A` [Knight's Tour](src/algorithms/uncategorized/knight-tour) * **Branch & Bound** - remember the lowest-cost solution found at each stage of the backtracking search, and use the cost of the lowest-cost solution found so far as a lower bound on the cost of a least-cost solution to the problem, in order to discard partial solutions with costs larger than the From 42c7a15976738156763da5daf2327f79680941d6 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Fri, 22 Jun 2018 15:44:46 +0300 Subject: [PATCH 30/44] Update READMEs. --- README.zh-CN.md | 180 ++++++++++++++++++++++++------------------------ README.zh-TW.md | 180 ++++++++++++++++++++++++------------------------ 2 files changed, 180 insertions(+), 180 deletions(-) diff --git a/README.zh-CN.md b/README.zh-CN.md index 3a9d7635ad..f42e6d98a0 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -9,25 +9,25 @@ _Read this in other languages:_ [_English_](https://github.com/trekhleb/javascript-algorithms/), -[繁體中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-TW.md) +[繁體中文](README.zh-TW.md) ## 数据结构 数据结构是在计算机中组织和存储数据的一种特殊方式,它可以高效地访问和修改数据。更确切地说,数据结构是数据值的集合,它们之间的关系、函数或操作可以应用于数据。 -* [链表](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list) -* [队列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue) -* [栈](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) -* [哈希表](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) -* [堆](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) -* [优先队列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) -* [字典树](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) -* [树](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) - * [二分查找](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) - * [AVL 树](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) - * [红黑树](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/red-black-tree) -* [图](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/graph) (有向图与无向图) -* [并查集](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/disjoint-set) +* [链表](src/data-structures/linked-list) +* [队列](src/data-structures/queue) +* [栈](src/data-structures/stack) +* [哈希表](src/data-structures/hash-table) +* [堆](src/data-structures/heap) +* [优先队列](src/data-structures/priority-queue) +* [字典树](src/data-structures/trie) +* [树](src/data-structures/tree) + * [二分查找](src/data-structures/tree/binary-search-tree) + * [AVL 树](src/data-structures/tree/avl-tree) + * [红黑树](src/data-structures/tree/red-black-tree) +* [图](src/data-structures/graph) (有向图与无向图) +* [并查集](src/data-structures/disjoint-set) ## 算法 @@ -36,61 +36,61 @@ _Read this in other languages:_ ### 算法主题 * **数学** - * [阶乘](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial) - * [斐波那契数](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [素数检测](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (排除法) - * [欧几里得算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - 计算最大公约数(GCD) - * [最小公倍数](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM) - * [整数拆分](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) + * [阶乘](src/algorithms/math/factorial) + * [斐波那契数](src/algorithms/math/fibonacci) + * [素数检测](src/algorithms/math/primality-test) (排除法) + * [欧几里得算法](src/algorithms/math/euclidean-algorithm) - 计算最大公约数(GCD) + * [最小公倍数](src/algorithms/math/least-common-multiple) (LCM) + * [整数拆分](src/algorithms/math/integer-partition) * **集合** - * [笛卡尔积](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - 多集合结果 - * [幂集](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - 该集合的所有子集 - * [排列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (有/无重复) - * [组合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (有/无重复) - * [洗牌算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - 随机置换有限序列 - * [最长公共子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence) (LCS) - * [最长递增子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS) - * [背包问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones - * [最大子数列问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - BF算法 与 动态编程 + * [笛卡尔积](src/algorithms/sets/cartesian-product) - 多集合结果 + * [幂集](src/algorithms/sets/power-set) - 该集合的所有子集 + * [排列](src/algorithms/sets/permutations) (有/无重复) + * [组合](src/algorithms/sets/combinations) (有/无重复) + * [洗牌算法](src/algorithms/sets/fisher-yates) - 随机置换有限序列 + * [最长公共子序列](src/algorithms/sets/longest-common-subsequence) (LCS) + * [最长递增子序列](src/algorithms/sets/longest-increasing-subsequence) + * [Shortest Common Supersequence](src/algorithms/sets/shortest-common-supersequence) (SCS) + * [背包问题](src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones + * [最大子数列问题](src/algorithms/sets/maximum-subarray) - BF算法 与 动态编程 * **字符串** - * [莱温斯坦距离](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - 两个序列之间的最小编辑距离 - * [汉明距离](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - 符号不同的位置数 - * [克努斯-莫里斯-普拉特算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - 子串搜索 - * [字符串快速查找](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - 子串搜索 - * [最长公共子串](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) + * [莱温斯坦距离](src/algorithms/string/levenshtein-distance) - 两个序列之间的最小编辑距离 + * [汉明距离](src/algorithms/string/hamming-distance) - 符号不同的位置数 + * [克努斯-莫里斯-普拉特算法](src/algorithms/string/knuth-morris-pratt) - 子串搜索 + * [字符串快速查找](src/algorithms/string/rabin-karp) - 子串搜索 + * [最长公共子串](src/algorithms/string/longest-common-substring) * **搜索** - * [二分查找](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) + * [二分查找](src/algorithms/search/binary-search) * **排序** - * [冒泡排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort) - * [选择排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort) - * [插入排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) - * [堆排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) - * [归并排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [快速排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * [希尔排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort) + * [冒泡排序](src/algorithms/sorting/bubble-sort) + * [选择排序](src/algorithms/sorting/selection-sort) + * [插入排序](src/algorithms/sorting/insertion-sort) + * [堆排序](src/algorithms/sorting/heap-sort) + * [归并排序](src/algorithms/sorting/merge-sort) + * [快速排序](src/algorithms/sorting/quick-sort) + * [希尔排序](src/algorithms/sorting/shell-sort) * **树** - * [深度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [广度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/breadth-first-search) (BFS) + * [深度优先搜索](src/algorithms/tree/depth-first-search) (DFS) + * [广度优先搜索](src/algorithms/tree/breadth-first-search) (BFS) * **图** - * [深度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) - * [广度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/breadth-first-search) (BFS) - * [戴克斯特拉算法m](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - 找到所有图顶点的最短路径 - * [贝尔曼-福特算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - 找到所有图顶点的最短路径 - * [判圈算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/detect-cycle) - 对于有向图和无向图(基于DFS和不相交集的版本) - * [普林演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - 寻找加权无向图的最小生成树(MST) - * [克鲁斯克尔演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - 寻找加权无向图的最小生成树(MST) - * [拓撲排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/topological-sorting) - DFS 方法 - * [关节点](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/articulation-points) - Tarjan算法(基于DFS) - * [桥](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bridges) - 基于DFS的算法 - * [欧拉路径与一笔画问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/eulerian-path) - Fleury的算法 - 一次访问每个边缘 - * [哈密顿图](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - 恰好访问每个顶点一次 - * [强连通分量](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/strongly-connected-components) - Kosaraju算法 - * [旅行推销员问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - 尽可能以最短的路线访问每个城市并返回原始城市 + * [深度优先搜索](src/algorithms/graph/depth-first-search) (DFS) + * [广度优先搜索](src/algorithms/graph/breadth-first-search) (BFS) + * [戴克斯特拉算法m](src/algorithms/graph/dijkstra) - 找到所有图顶点的最短路径 + * [贝尔曼-福特算法](src/algorithms/graph/bellman-ford) - 找到所有图顶点的最短路径 + * [判圈算法](src/algorithms/graph/detect-cycle) - 对于有向图和无向图(基于DFS和不相交集的版本) + * [普林演算法](src/algorithms/graph/prim) - 寻找加权无向图的最小生成树(MST) + * [克鲁斯克尔演算法](src/algorithms/graph/kruskal) - 寻找加权无向图的最小生成树(MST) + * [拓撲排序](src/algorithms/graph/topological-sorting) - DFS 方法 + * [关节点](src/algorithms/graph/articulation-points) - Tarjan算法(基于DFS) + * [桥](src/algorithms/graph/bridges) - 基于DFS的算法 + * [欧拉路径与一笔画问题](src/algorithms/graph/eulerian-path) - Fleury的算法 - 一次访问每个边缘 + * [哈密顿图](src/algorithms/graph/hamiltonian-cycle) - 恰好访问每个顶点一次 + * [强连通分量](src/algorithms/graph/strongly-connected-components) - Kosaraju算法 + * [旅行推销员问题](src/algorithms/graph/travelling-salesman) - 尽可能以最短的路线访问每个城市并返回原始城市 * **未分类** - * [汉诺塔](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [八皇后问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [骑士巡逻](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * [汉诺塔](src/algorithms/uncategorized/hanoi-tower) + * [八皇后问题](src/algorithms/uncategorized/n-queens) + * [骑士巡逻](src/algorithms/uncategorized/knight-tour) ### 算法范式 @@ -98,39 +98,39 @@ _Read this in other languages:_ 算法是比计算机程序更高的抽象。 * **BF算法** - 查找所有可能性并选择最佳解决方案 - * [最大子数列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [旅行推销员问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - 尽可能以最短的路线访问每个城市并返回原始城市 + * [最大子数列](src/algorithms/sets/maximum-subarray) + * [旅行推销员问题](src/algorithms/graph/travelling-salesman) - 尽可能以最短的路线访问每个城市并返回原始城市 * **贪心法** - 在当前选择最佳选项,不考虑以后情况 - * [背包问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [戴克斯特拉算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - 找到所有图顶点的最短路径 - * [普里姆算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - 寻找加权无向图的最小生成树(MST) - * [克鲁斯卡尔算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - 寻找加权无向图的最小生成树(MST) + * [背包问题](src/algorithms/sets/knapsack-problem) + * [戴克斯特拉算法](src/algorithms/graph/dijkstra) - 找到所有图顶点的最短路径 + * [普里姆算法](src/algorithms/graph/prim) - 寻找加权无向图的最小生成树(MST) + * [克鲁斯卡尔算法](src/algorithms/graph/kruskal) - 寻找加权无向图的最小生成树(MST) * **分治法** - 将问题分成较小的部分,然后解决这些部分 - * [二分查找](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) - * [汉诺塔](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [欧几里得算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - 计算最大公约数(GCD) - * [排列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (有/无重复) - * [组合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (有/无重复) - * [归并排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * [树深度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [图深度优先搜索](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) + * [二分查找](src/algorithms/search/binary-search) + * [汉诺塔](src/algorithms/uncategorized/hanoi-tower) + * [欧几里得算法](src/algorithms/math/euclidean-algorithm) - 计算最大公约数(GCD) + * [排列](src/algorithms/sets/permutations) (有/无重复) + * [组合](src/algorithms/sets/combinations) (有/无重复) + * [归并排序](src/algorithms/sorting/merge-sort) + * [Quicksort](src/algorithms/sorting/quick-sort) + * [树深度优先搜索](src/algorithms/tree/depth-first-search) (DFS) + * [图深度优先搜索](src/algorithms/graph/depth-first-search) (DFS) * **动态编程** - 使用以前找到的子解决方案构建解决方案 - * [斐波那契数](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [莱温斯坦距离](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - 两个序列之间的最小编辑距离 - * [最长公共子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS) - * [最长公共子串](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) - * [最长递增子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [最短公共子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) - * [0-1背包问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [整数拆分](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * [最大子数列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [贝尔曼-福特算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - 找到所有图顶点的最短路径 + * [斐波那契数](src/algorithms/math/fibonacci) + * [莱温斯坦距离](src/algorithms/string/levenshtein-distance) - 两个序列之间的最小编辑距离 + * [最长公共子序列](src/algorithms/sets/longest-common-subsequence) (LCS) + * [最长公共子串](src/algorithms/string/longest-common-substring) + * [最长递增子序列](src/algorithms/sets/longest-increasing-subsequence) + * [最短公共子序列](src/algorithms/sets/shortest-common-supersequence) + * [0-1背包问题](src/algorithms/sets/knapsack-problem) + * [整数拆分](src/algorithms/math/integer-partition) + * [最大子数列](src/algorithms/sets/maximum-subarray) + * [贝尔曼-福特算法](src/algorithms/graph/bellman-ford) - 找到所有图顶点的最短路径 * **回溯法** - 类似于 BF算法 试图产生所有可能的解决方案,但每次生成解决方案测试如果它满足所有条件,那么只有继续生成后续解决方案。 否则回溯并继续寻找不同路径的解决方案。 - * [哈密顿图](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - 恰好访问每个顶点一次 - * [八皇后问题](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [骑士巡逻](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * [哈密顿图](src/algorithms/graph/hamiltonian-cycle) - 恰好访问每个顶点一次 + * [八皇后问题](src/algorithms/uncategorized/n-queens) + * [骑士巡逻](src/algorithms/uncategorized/knight-tour) * **B & B** ## 如何使用本仓库 diff --git a/README.zh-TW.md b/README.zh-TW.md index e295b47994..8804630450 100644 --- a/README.zh-TW.md +++ b/README.zh-TW.md @@ -8,25 +8,25 @@ _Read this in other languages:_ [_English_](https://github.com/trekhleb/javascript-algorithms/), -[简体中文](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-CN.md) +[简体中文](README.zh-CN.md) ## 資料結構 資料結構是一個電腦用來組織和排序資料的特定方式,透過這樣的方式資料可以有效率地被讀取以及修改。更精確地說,一個資料結構是一個資料值的集合、彼此間的關係,函數或者運作可以應用於資料上。 -* [鏈結串列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/linked-list) -* [貯列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/queue) -* [堆疊](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) -* [雜湊表](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) -* [堆](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) -* [優先貯列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) -* [字典樹](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) -* [樹](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) - * [二元搜尋樹](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) - * [AVL樹](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) - * [紅黑樹](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/red-black-tree) -* [圖](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/graph) (有向跟無向皆包含) -* [互斥集](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/disjoint-set) +* [鏈結串列](src/data-structures/linked-list) +* [貯列](src/data-structures/queue) +* [堆疊](src/data-structures/stack) +* [雜湊表](src/data-structures/hash-table) +* [堆](src/data-structures/heap) +* [優先貯列](src/data-structures/priority-queue) +* [字典樹](src/data-structures/trie) +* [樹](src/data-structures/tree) + * [二元搜尋樹](src/data-structures/tree/binary-search-tree) + * [AVL樹](src/data-structures/tree/avl-tree) + * [紅黑樹](src/data-structures/tree/red-black-tree) +* [圖](src/data-structures/graph) (有向跟無向皆包含) +* [互斥集](src/data-structures/disjoint-set) ## 演算法 @@ -35,99 +35,99 @@ _Read this in other languages:_ ### 演算法議題分類 * **數學類** - * [階層](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/factorial) - * [費伯納西數列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [Primality Test](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/primality-test) (排除法) - * [歐幾里得算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - 計算最大公因數 (GCD) - * [最小公倍數](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/least-common-multiple) (LCM) - * [整數拆分](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) + * [階層](src/algorithms/math/factorial) + * [費伯納西數列](src/algorithms/math/fibonacci) + * [Primality Test](src/algorithms/math/primality-test) (排除法) + * [歐幾里得算法](src/algorithms/math/euclidean-algorithm) - 計算最大公因數 (GCD) + * [最小公倍數](src/algorithms/math/least-common-multiple) (LCM) + * [整數拆分](src/algorithms/math/integer-partition) * **集合** - * [笛卡爾積](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/cartesian-product) - 多個集合的乘積 - * [冪集合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/power-set) - 所有集合的子集合 - * [排列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (有/無重複) - * [组合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (有/無重複) - * [洗牌算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/fisher-yates) - 隨機置換一有限序列 - * [最長共同子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequence) (LCS) - * [最長遞增子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [Shortest Common Supersequence](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) (SCS) - * [背包問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones - * [最大子序列問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - 暴力法以及動態編程的(Kadane's)版本 + * [笛卡爾積](src/algorithms/sets/cartesian-product) - 多個集合的乘積 + * [冪集合](src/algorithms/sets/power-set) - 所有集合的子集合 + * [排列](src/algorithms/sets/permutations) (有/無重複) + * [组合](src/algorithms/sets/combinations) (有/無重複) + * [洗牌算法](src/algorithms/sets/fisher-yates) - 隨機置換一有限序列 + * [最長共同子序列](src/algorithms/sets/longest-common-subsequence) (LCS) + * [最長遞增子序列](src/algorithms/sets/longest-increasing-subsequence) + * [Shortest Common Supersequence](src/algorithms/sets/shortest-common-supersequence) (SCS) + * [背包問題](src/algorithms/sets/knapsack-problem) - "0/1" and "Unbound" ones + * [最大子序列問題](src/algorithms/sets/maximum-subarray) - 暴力法以及動態編程的(Kadane's)版本 * **字串** - * [萊文斯坦距離](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - 兩序列間的最小編輯距離 - * [漢明距離](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/hamming-distance) - number of positions at which the symbols are different - * [KMP 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/knuth-morris-pratt) - 子字串搜尋 - * [Rabin Karp 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/rabin-karp) - 子字串搜尋 - * [最長共通子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) + * [萊文斯坦距離](src/algorithms/string/levenshtein-distance) - 兩序列間的最小編輯距離 + * [漢明距離](src/algorithms/string/hamming-distance) - number of positions at which the symbols are different + * [KMP 演算法](src/algorithms/string/knuth-morris-pratt) - 子字串搜尋 + * [Rabin Karp 演算法](src/algorithms/string/rabin-karp) - 子字串搜尋 + * [最長共通子序列](src/algorithms/string/longest-common-substring) * **搜尋** - * [二元搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) + * [二元搜尋](src/algorithms/search/binary-search) * **排序** - * [氣泡排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort) - * [選擇排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort) - * [插入排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort) - * [堆排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort) - * [合併排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [快速排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * [希爾排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort) + * [氣泡排序](src/algorithms/sorting/bubble-sort) + * [選擇排序](src/algorithms/sorting/selection-sort) + * [插入排序](src/algorithms/sorting/insertion-sort) + * [堆排序](src/algorithms/sorting/heap-sort) + * [合併排序](src/algorithms/sorting/merge-sort) + * [快速排序](src/algorithms/sorting/quick-sort) + * [希爾排序](src/algorithms/sorting/shell-sort) * **樹** - * [深度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [廣度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/breadth-first-search) (BFS) + * [深度優先搜尋](src/algorithms/tree/depth-first-search) (DFS) + * [廣度優先搜尋](src/algorithms/tree/breadth-first-search) (BFS) * **圖** - * [深度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) - * [廣度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/breadth-first-search) (BFS) - * [Dijkstra 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - 找到所有圖頂點的最短路徑 - * [Bellman-Ford 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - 找到所有圖頂點的最短路徑 - * [Detect Cycle](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) - * [Prim’s 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [Kruskal’s 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [拓撲排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/topological-sorting) - DFS method - * [關節點](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) - * [橋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bridges) - DFS based algorithm - * [尤拉路徑及尤拉環](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once - * [漢彌爾頓環](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * [強連通組件](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm - * [旅行推銷員問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * [深度優先搜尋](src/algorithms/graph/depth-first-search) (DFS) + * [廣度優先搜尋](src/algorithms/graph/breadth-first-search) (BFS) + * [Dijkstra 演算法](src/algorithms/graph/dijkstra) - 找到所有圖頂點的最短路徑 + * [Bellman-Ford 演算法](src/algorithms/graph/bellman-ford) - 找到所有圖頂點的最短路徑 + * [Detect Cycle](src/algorithms/graph/detect-cycle) - for both directed and undirected graphs (DFS and Disjoint Set based versions) + * [Prim’s 演算法](src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * [Kruskal’s 演算法](src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * [拓撲排序](src/algorithms/graph/topological-sorting) - DFS method + * [關節點](src/algorithms/graph/articulation-points) - Tarjan's algorithm (DFS based) + * [橋](src/algorithms/graph/bridges) - DFS based algorithm + * [尤拉路徑及尤拉環](src/algorithms/graph/eulerian-path) - Fleury's algorithm - Visit every edge exactly once + * [漢彌爾頓環](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * [強連通組件](src/algorithms/graph/strongly-connected-components) - Kosaraju's algorithm + * [旅行推銷員問題](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **未分類** - * [河內塔](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [N-皇后問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [騎士走棋盤](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * [河內塔](src/algorithms/uncategorized/hanoi-tower) + * [N-皇后問題](src/algorithms/uncategorized/n-queens) + * [騎士走棋盤](src/algorithms/uncategorized/knight-tour) ### 演算法範型 演算法的範型是一個泛用方法或設計一類底層演算法的方式。它是一個比演算法的概念更高階的抽象化,就像是演算法是比電腦程式更高階的抽象化。 * **暴力法** - 尋遍所有的可能解然後選取最好的解 - * [最大子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [旅行推銷員問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city + * [最大子序列](src/algorithms/sets/maximum-subarray) + * [旅行推銷員問題](src/algorithms/graph/travelling-salesman) - shortest possible route that visits each city and returns to the origin city * **貪婪法** - choose the best option at the current time, without any consideration for the future - * [未定背包問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [Dijkstra 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/dijkstra) - 找到所有圖頂點的最短路徑 - * [Prim’s 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph - * [Kruskal’s 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * [未定背包問題](src/algorithms/sets/knapsack-problem) + * [Dijkstra 演算法](src/algorithms/graph/dijkstra) - 找到所有圖頂點的最短路徑 + * [Prim’s 演算法](src/algorithms/graph/prim) - finding Minimum Spanning Tree (MST) for weighted undirected graph + * [Kruskal’s 演算法](src/algorithms/graph/kruskal) - finding Minimum Spanning Tree (MST) for weighted undirected graph * **分治法** - divide the problem into smaller parts and then solve those parts - * [二元搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/search/binary-search) - * [河內塔](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/hanoi-tower) - * [歐幾里得演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) - * [排列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/permutations) (有/無重複) - * [组合](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/combinations) (有/無重複) - * [合併排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort) - * [快速排序](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort) - * [樹深度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/tree/depth-first-search) (DFS) - * [圖深度優先搜尋](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/depth-first-search) (DFS) + * [二元搜尋](src/algorithms/search/binary-search) + * [河內塔](src/algorithms/uncategorized/hanoi-tower) + * [歐幾里得演算法](src/algorithms/math/euclidean-algorithm) - calculate the Greatest Common Divisor (GCD) + * [排列](src/algorithms/sets/permutations) (有/無重複) + * [组合](src/algorithms/sets/combinations) (有/無重複) + * [合併排序](src/algorithms/sorting/merge-sort) + * [快速排序](src/algorithms/sorting/quick-sort) + * [樹深度優先搜尋](src/algorithms/tree/depth-first-search) (DFS) + * [圖深度優先搜尋](src/algorithms/graph/depth-first-search) (DFS) * **動態編程** - build up to a solution using previously found sub-solutions - * [費伯納西數列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/fibonacci) - * [萊溫斯坦距離](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences - * [最長共同子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-common-subsequnce) (LCS) - * [最長共同子字串](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/string/longest-common-substring) - * [最長遞增子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/longest-increasing-subsequence) - * [最短共同子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/shortest-common-supersequence) - * [0/1背包問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/knapsack-problem) - * [整數拆分](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/math/integer-partition) - * [最大子序列](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sets/maximum-subarray) - * [Bellman-Ford 演算法](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * [費伯納西數列](src/algorithms/math/fibonacci) + * [萊溫斯坦距離](src/algorithms/string/levenshtein-distance) - minimum edit distance between two sequences + * [最長共同子序列](src/algorithms/sets/longest-common-subsequnce) (LCS) + * [最長共同子字串](src/algorithms/string/longest-common-substring) + * [最長遞增子序列](src/algorithms/sets/longest-increasing-subsequence) + * [最短共同子序列](src/algorithms/sets/shortest-common-supersequence) + * [0/1背包問題](src/algorithms/sets/knapsack-problem) + * [整數拆分](src/algorithms/math/integer-partition) + * [最大子序列](src/algorithms/sets/maximum-subarray) + * [Bellman-Ford 演算法](src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices * **回溯法** - 用類似暴力法來嘗試產生所有可能解,但每次只在能滿足所有測試條件,且只有繼續產生子序列方案來產生的解決方案。否則回溯並尋找不同路徑的解決方案。 - * [漢彌爾頓迴路](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once - * [N-皇后問題](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/n-queens) - * [騎士走棋盤](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/uncategorized/knight-tour) + * [漢彌爾頓迴路](src/algorithms/graph/hamiltonian-cycle) - Visit every vertex exactly once + * [N-皇后問題](src/algorithms/uncategorized/n-queens) + * [騎士走棋盤](src/algorithms/uncategorized/knight-tour) * **Branch & Bound** ## 如何使用本知識庫 From a9502851f50af1808e2155eaf0d4fe8079fd109e Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Sat, 23 Jun 2018 13:21:07 +0300 Subject: [PATCH 31/44] Update READMEs. --- src/data-structures/tree/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/data-structures/tree/README.md b/src/data-structures/tree/README.md index 13445b7fd7..42e69cc68b 100644 --- a/src/data-structures/tree/README.md +++ b/src/data-structures/tree/README.md @@ -1,7 +1,10 @@ # Tree -* [Binary Search Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) -* [AVL Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/avl-tree) +* [Binary Search Tree](binary-search-tree) +* [AVL Tree](avl-tree) +* [Red-Black Tree](red-black-tree) +* [Segment Tree](segment-tree) - with min/max/sum range queries examples +* [Fenwick Tree](fenwick-tree) (Binary Indexed Tree) In computer science, a tree is a widely used abstract data type (ADT) — or data structure implementing this ADT—that From 89fb0e62396b939472e74da4db294425dbc7d5f9 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Sat, 23 Jun 2018 20:59:59 +0300 Subject: [PATCH 32/44] Add Levenshtein Distance algorithm explanations. --- .../string/levenshtein-distance/README.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/algorithms/string/levenshtein-distance/README.md b/src/algorithms/string/levenshtein-distance/README.md index 00019e87fd..cc5b5e9d7f 100644 --- a/src/algorithms/string/levenshtein-distance/README.md +++ b/src/algorithms/string/levenshtein-distance/README.md @@ -40,7 +40,76 @@ three edits: 2. sitt**e**n → sitt**i**n (substitution of "i" for "e") 3. sittin → sittin**g** (insertion of "g" at the end). +## Applications + +This has a wide range of applications, for instance, spell checkers, correction +systems for optical character recognition, fuzzy string searching, and software +to assist natural language translation based on translation memory. + +## Dynamic Programming Approach Explanation + +Let’s take a simple example of finding minimum edit distance between +strings `ME` and `MY`. Intuitively you already know that minimum edit distance +here is `1` operation and this operation. And it is a replacing `E` with `Y`. But +let’s try to formalize it in a form of the algorithm in order to be able to +do more complex examples like transforming `Saturday` into `Sunday`. + +To apply the mathematical formula mentioned above to `ME → MY` transformation +we need to know minimum edit distances of `ME → M`, `M → MY` and `M → M` transformations +in prior. Then we will need to pick the minimum one and add _one_ operation to +transform last letters `E → Y`. So minimum edit distance of `ME → MY` transformation +is being calculated based on three previously possible transformations. + +To explain this further let’s draw the following matrix: + +![Levenshtein Matrix](https://cdn-images-1.medium.com/max/1600/1*2d46ug_PL5LfeqztckoYGw.jpeg) + +- Cell `(0:1)` contains red number 1. It means that we need 1 operation to +transform `M` to an empty string. And it is by deleting `M`. This is why this number is red. +- Cell `(0:2)` contains red number 2. It means that we need 2 operations +to transform `ME` to an empty string. And it is by deleting `E` and `M`. +- Cell `(1:0)` contains green number 1. It means that we need 1 operation +to transform an empty string to `M`. And it is by inserting `M`. This is why this number is green. +- Cell `(2:0)` contains green number 2. It means that we need 2 operations +to transform an empty string to `MY`. And it is by inserting `Y` and `M`. +- Cell `(1:1)` contains number 0. It means that it costs nothing +to transform `M` into `M`. +- Cell `(1:2)` contains red number 1. It means that we need 1 operation +to transform `ME` to `M`. And it is be deleting `E`. +- And so on... + +This looks easy for such small matrix as ours (it is only `3x3`). But here you +may find basic concepts that may be applied to calculate all those numbers for +bigger matrices (let’s say `9x7` one, for `Saturday → Sunday` transformation). + +According to the formula you only need three adjacent cells `(i-1:j)`, `(i-1:j-1)`, and `(i:j-1)` to +calculate the number for current cell `(i:j)`. All we need to do is to find the +minimum of those three cells and then add `1` in case if we have different +letters in `i`'s row and `j`'s column. + +You may clearly see the recursive nature of the problem. + +![Levenshtein Matrix](https://cdn-images-1.medium.com/max/2000/1*JdHQ5TeKiDlE-iKK1s_2vw.jpeg) + +Let's draw a decision graph for this problem. + +![Minimum Edit Distance Decision Graph](https://cdn-images-1.medium.com/max/1600/1*SGwYUpXH9H1xUeTvJk0e7Q.jpeg) + +You may see a number of overlapping sub-problems on the picture that are marked +with red. Also there is no way to reduce the number of operations and make it +less then a minimum of those three adjacent cells from the formula. + +Also you may notice that each cell number in the matrix is being calculated +based on previous ones. Thus the tabulation technique (filling the cache in +bottom-up direction) is being applied here. + +Applying this principles further we may solve more complicated cases like +with `Saturday → Sunday` transformation. + +![Levenshtein distance](https://cdn-images-1.medium.com/max/1600/1*fPEHiImYLKxSTUhrGbYq3g.jpeg) + ## References - [Wikipedia](https://en.wikipedia.org/wiki/Levenshtein_distance) - [YouTube](https://www.youtube.com/watch?v=We3YDTzNXEk&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) +- [ITNext](https://itnext.io/dynamic-programming-vs-divide-and-conquer-2fea680becbe) From 88d038b5c8899867d09d2e96237104add3216f19 Mon Sep 17 00:00:00 2001 From: m-maksyutin Date: Mon, 25 Jun 2018 14:33:31 +0300 Subject: [PATCH 33/44] Fix the findEdge method of the graph (#80) * Fix LinkedList * Fix the prepend method for the LinkedList * Fix the remove method for the MinHeap * Correct a comment * Fix BST removal method * Fix the findEdge method of the graph --- src/data-structures/graph/Graph.js | 3 +++ src/data-structures/graph/__test__/Graph.test.js | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/data-structures/graph/Graph.js b/src/data-structures/graph/Graph.js index e2ef20b7e0..8e603c389b 100644 --- a/src/data-structures/graph/Graph.js +++ b/src/data-structures/graph/Graph.js @@ -115,6 +115,9 @@ export default class Graph { */ findEdge(startVertex, endVertex) { const vertex = this.getVertexByKey(startVertex.getKey()); + if (!vertex) { + return null; + } return vertex.findEdge(endVertex); } diff --git a/src/data-structures/graph/__test__/Graph.test.js b/src/data-structures/graph/__test__/Graph.test.js index 1c6592ba55..be6e9d7fb2 100644 --- a/src/data-structures/graph/__test__/Graph.test.js +++ b/src/data-structures/graph/__test__/Graph.test.js @@ -87,9 +87,11 @@ describe('Graph', () => { const graphEdgeAB = graph.findEdge(vertexA, vertexB); const graphEdgeBA = graph.findEdge(vertexB, vertexA); - const graphEdgeAC = graph.findEdge(vertexB, vertexC); + const graphEdgeAC = graph.findEdge(vertexA, vertexC); + const graphEdgeCA = graph.findEdge(vertexC, vertexA); expect(graphEdgeAC).toBeNull(); + expect(graphEdgeCA).toBeNull(); expect(graphEdgeAB).toEqual(edgeAB); expect(graphEdgeBA).toEqual(edgeAB); expect(graphEdgeAB.weight).toBe(10); @@ -108,9 +110,11 @@ describe('Graph', () => { const graphEdgeAB = graph.findEdge(vertexA, vertexB); const graphEdgeBA = graph.findEdge(vertexB, vertexA); - const graphEdgeAC = graph.findEdge(vertexB, vertexC); + const graphEdgeAC = graph.findEdge(vertexA, vertexC); + const graphEdgeCA = graph.findEdge(vertexC, vertexA); expect(graphEdgeAC).toBeNull(); + expect(graphEdgeCA).toBeNull(); expect(graphEdgeBA).toBeNull(); expect(graphEdgeAB).toEqual(edgeAB); expect(graphEdgeAB.weight).toBe(10); From c96bbdf00e0876b2ea3e6386af7d6a0768e7b4d6 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 25 Jun 2018 14:34:40 +0300 Subject: [PATCH 34/44] Code style fix. --- src/data-structures/graph/Graph.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data-structures/graph/Graph.js b/src/data-structures/graph/Graph.js index 8e603c389b..ae123ca15c 100644 --- a/src/data-structures/graph/Graph.js +++ b/src/data-structures/graph/Graph.js @@ -115,9 +115,11 @@ export default class Graph { */ findEdge(startVertex, endVertex) { const vertex = this.getVertexByKey(startVertex.getKey()); + if (!vertex) { return null; } + return vertex.findEdge(endVertex); } From d69199e65867cee442602008f6da7d306c62107f Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 25 Jun 2018 20:02:24 +0300 Subject: [PATCH 35/44] Add regular expression matching algorithm. --- README.md | 2 + .../regular-expression-matching/README.md | 73 ++++++++++ .../regularExpressionMatching.test.js | 34 +++++ .../regularExpressionMatching.js | 135 ++++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 src/algorithms/string/regular-expression-matching/README.md create mode 100644 src/algorithms/string/regular-expression-matching/__test__/regularExpressionMatching.test.js create mode 100644 src/algorithms/string/regular-expression-matching/regularExpressionMatching.js diff --git a/README.md b/README.md index 7246abc1e5..088005fec9 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ a set of rules that precisely define a sequence of operations. * `A` [Z Algorithm](src/algorithms/string/z-algorithm) - substring search (pattern matching) * `A` [Rabin Karp Algorithm](src/algorithms/string/rabin-karp) - substring search * `A` [Longest Common Substring](src/algorithms/string/longest-common-substring) + * `A` [Regular Expression Matching](src/algorithms/string/regular-expression-matching) * **Searches** * `B` [Linear Search](src/algorithms/search/linear-search) * `B` [Binary Search](src/algorithms/search/binary-search) @@ -147,6 +148,7 @@ algorithm is an abstraction higher than a computer program. * `A` [Integer Partition](src/algorithms/math/integer-partition) * `A` [Maximum Subarray](src/algorithms/sets/maximum-subarray) * `A` [Bellman-Ford Algorithm](src/algorithms/graph/bellman-ford) - finding shortest path to all graph vertices + * `A` [Regular Expression Matching](src/algorithms/string/regular-expression-matching) * **Backtracking** - similarly to brute force, try to generate all possible solutions, but each time you generate next solution you test if it satisfies all conditions, and only then continue generating subsequent solutions. Otherwise, backtrack, and go on a different path of finding a solution. Normally the DFS traversal of state-space is being used. diff --git a/src/algorithms/string/regular-expression-matching/README.md b/src/algorithms/string/regular-expression-matching/README.md new file mode 100644 index 0000000000..e04c071e40 --- /dev/null +++ b/src/algorithms/string/regular-expression-matching/README.md @@ -0,0 +1,73 @@ +# Regular Expression Matching + +Given an input string `s` and a pattern `p`, implement regular +expression matching with support for `.` and `*`. + +- `.` Matches any single character. +- `*` Matches zero or more of the preceding element. + +The matching should cover the **entire** input string (not partial). + +**Note** + +- `s` could be empty and contains only lowercase letters `a-z`. +- `p` could be empty and contains only lowercase letters `a-z`, and characters like `.` or `*`. + +## Examples + +**Example #1** + +Input: +``` +s = 'aa' +p = 'a' +``` + +Output: `false` + +Explanation: `a` does not match the entire string `aa`. + +**Example #2** + +Input: +``` +s = 'aa' +p = 'a*' +``` + +Output: `true` + +Explanation: `*` means zero or more of the preceding element, `a`. +Therefore, by repeating `a` once, it becomes `aa`. + +**Example #3** + +Input: + +``` +s = 'ab' +p = '.*' +``` + +Output: `true` + +Explanation: `.*` means "zero or more (`*`) of any character (`.`)". + +**Example #4** + +Input: + +``` +s = 'aab' +p = 'c*a*b' +``` + +Output: `true` + +Explanation: `c` can be repeated 0 times, `a` can be repeated +1 time. Therefore it matches `aab`. + +## References + +- [YouTube](https://www.youtube.com/watch?v=l3hda49XcDE&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=71&t=0s) +- [LeetCode](https://leetcode.com/problems/regular-expression-matching/description/) diff --git a/src/algorithms/string/regular-expression-matching/__test__/regularExpressionMatching.test.js b/src/algorithms/string/regular-expression-matching/__test__/regularExpressionMatching.test.js new file mode 100644 index 0000000000..b1e676a68e --- /dev/null +++ b/src/algorithms/string/regular-expression-matching/__test__/regularExpressionMatching.test.js @@ -0,0 +1,34 @@ +import regularExpressionMatching from '../regularExpressionMatching'; + +describe('regularExpressionMatching', () => { + it('should match regular expressions in a string', () => { + expect(regularExpressionMatching('', '')).toBeTruthy(); + expect(regularExpressionMatching('a', 'a')).toBeTruthy(); + expect(regularExpressionMatching('aa', 'aa')).toBeTruthy(); + expect(regularExpressionMatching('aab', 'aab')).toBeTruthy(); + expect(regularExpressionMatching('aab', 'aa.')).toBeTruthy(); + expect(regularExpressionMatching('aab', '.a.')).toBeTruthy(); + expect(regularExpressionMatching('aab', '...')).toBeTruthy(); + expect(regularExpressionMatching('a', 'a*')).toBeTruthy(); + expect(regularExpressionMatching('aaa', 'a*')).toBeTruthy(); + expect(regularExpressionMatching('aaab', 'a*b')).toBeTruthy(); + expect(regularExpressionMatching('aaabb', 'a*b*')).toBeTruthy(); + expect(regularExpressionMatching('aaabb', 'a*b*c*')).toBeTruthy(); + expect(regularExpressionMatching('', 'a*')).toBeTruthy(); + expect(regularExpressionMatching('xaabyc', 'xa*b.c')).toBeTruthy(); + expect(regularExpressionMatching('aab', 'c*a*b*')).toBeTruthy(); + expect(regularExpressionMatching('mississippi', 'mis*is*.p*.')).toBeTruthy(); + expect(regularExpressionMatching('ab', '.*')).toBeTruthy(); + + expect(regularExpressionMatching('', 'a')).toBeFalsy(); + expect(regularExpressionMatching('a', '')).toBeFalsy(); + expect(regularExpressionMatching('aab', 'aa')).toBeFalsy(); + expect(regularExpressionMatching('aab', 'baa')).toBeFalsy(); + expect(regularExpressionMatching('aabc', '...')).toBeFalsy(); + expect(regularExpressionMatching('aaabbdd', 'a*b*c*')).toBeFalsy(); + expect(regularExpressionMatching('mississippi', 'mis*is*p*.')).toBeFalsy(); + expect(regularExpressionMatching('ab', 'a*')).toBeFalsy(); + expect(regularExpressionMatching('abba', 'a*b*.c')).toBeFalsy(); + expect(regularExpressionMatching('abba', '.*c')).toBeFalsy(); + }); +}); diff --git a/src/algorithms/string/regular-expression-matching/regularExpressionMatching.js b/src/algorithms/string/regular-expression-matching/regularExpressionMatching.js new file mode 100644 index 0000000000..07ca0e2beb --- /dev/null +++ b/src/algorithms/string/regular-expression-matching/regularExpressionMatching.js @@ -0,0 +1,135 @@ +const ZERO_OR_MORE_CHARS = '*'; +const ANY_CHAR = '.'; + +/** + * Dynamic programming approach. + * + * @param {string} string + * @param {string} pattern + * @return {boolean} + */ +export default function regularExpressionMatching(string, pattern) { + /* + * Let's initiate dynamic programming matrix for this string and pattern. + * We will have pattern characters on top (as columns) and string characters + * will be placed to the left of the table (as rows). + * + * Example: + * + * a * b . b + * - - - - - - + * a - - - - - - + * a - - - - - - + * b - - - - - - + * y - - - - - - + * b - - - - - - + */ + const matchMatrix = Array(string.length + 1).fill(null).map(() => { + return Array(pattern.length + 1).fill(null); + }); + + // Let's fill the top-left cell with true. This would mean that empty + // string '' matches to empty pattern ''. + matchMatrix[0][0] = true; + + // Let's fill the first row of the matrix with false. That would mean that + // empty string can't match any non-empty pattern. + // + // Example: + // string: '' + // pattern: 'a.z' + // + // The one exception here is patterns like a*b* that matches the empty string. + for (let columnIndex = 1; columnIndex <= pattern.length; columnIndex += 1) { + const patternIndex = columnIndex - 1; + + if (pattern[patternIndex] === ZERO_OR_MORE_CHARS) { + matchMatrix[0][columnIndex] = matchMatrix[0][columnIndex - 2]; + } else { + matchMatrix[0][columnIndex] = false; + } + } + + // Let's fill the first column with false. That would mean that empty pattern + // can't match any non-empty string. + // + // Example: + // string: 'ab' + // pattern: '' + for (let rowIndex = 1; rowIndex <= string.length; rowIndex += 1) { + matchMatrix[rowIndex][0] = false; + } + + // Not let's go through every letter of the pattern and every letter of + // the string and compare them one by one. + for (let rowIndex = 1; rowIndex <= string.length; rowIndex += 1) { + for (let columnIndex = 1; columnIndex <= pattern.length; columnIndex += 1) { + // Take into account that fact that matrix contain one extra column and row. + const stringIndex = rowIndex - 1; + const patternIndex = columnIndex - 1; + + if (pattern[patternIndex] === ZERO_OR_MORE_CHARS) { + /* + * In case if current pattern character is special '*' character we have + * two options: + * + * 1. Since * char allows it previous char to not be presented in a string we + * need to check if string matches the pattern without '*' char and without the + * char that goes before '*'. That would mean to go two positions left on the + * same row. + * + * 2. Since * char allows it previous char to be presented in a string many times we + * need to check if char before * is the same as current string char. If they are the + * same that would mean that current string matches the current pattern in case if + * the string WITHOUT current char matches the same pattern. This would mean to go + * one position up in the same row. + */ + if (matchMatrix[rowIndex][columnIndex - 2] === true) { + matchMatrix[rowIndex][columnIndex] = true; + } else if ( + ( + pattern[patternIndex - 1] === string[stringIndex] || + pattern[patternIndex - 1] === ANY_CHAR + ) && + matchMatrix[rowIndex - 1][columnIndex] === true + ) { + matchMatrix[rowIndex][columnIndex] = true; + } else { + matchMatrix[rowIndex][columnIndex] = false; + } + } else if ( + pattern[patternIndex] === string[stringIndex] || + pattern[patternIndex] === ANY_CHAR + ) { + /* + * In case if current pattern char is the same as current string char + * or it may be any character (in case if pattern contains '.' char) + * we need to check if there was a match for the pattern and for the + * string by WITHOUT current char. This would mean that we may copy + * left-top diagonal value. + * + * Example: + * + * a b + * a 1 - + * b - 1 + */ + matchMatrix[rowIndex][columnIndex] = matchMatrix[rowIndex - 1][columnIndex - 1]; + } else { + /* + * In case if pattern char and string char are different we may + * treat this case as "no-match". + * + * Example: + * + * a b + * a - - + * c - 0 + */ + matchMatrix[rowIndex][columnIndex] = false; + } + } + } + + return matchMatrix[string.length][pattern.length]; +} From 36e0bfeb324290f4c61923067cb27255c01af224 Mon Sep 17 00:00:00 2001 From: m-maksyutin Date: Wed, 27 Jun 2018 16:22:54 +0300 Subject: [PATCH 36/44] Fix the value returned by DisjointSet union (#81) * Fix LinkedList * Fix the prepend method for the LinkedList * Fix the remove method for the MinHeap * Correct a comment * Fix BST removal method * Fix the findEdge method of the graph * Fix the value returned by DisjointSet union --- src/data-structures/disjoint-set/DisjointSet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data-structures/disjoint-set/DisjointSet.js b/src/data-structures/disjoint-set/DisjointSet.js index 2952f0a1b8..2fe3c25c3c 100644 --- a/src/data-structures/disjoint-set/DisjointSet.js +++ b/src/data-structures/disjoint-set/DisjointSet.js @@ -70,7 +70,7 @@ export default class DisjointSet { // If rootB's tree is bigger then make rootB to be a new root. rootB.addChild(rootA); - return rootB.getKey(); + return this; } // If rootA's tree is bigger then make rootA to be a new root. From 792f4906df14fc8d193f1b2ad3d405a3646055a9 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 27 Jun 2018 17:19:20 +0300 Subject: [PATCH 37/44] Add bit manipulation section. --- README.md | 1 + src/algorithms/math/bits/README.md | 37 +++++++++++++++++++ .../math/bits/__test__/clearBit.test.js | 15 ++++++++ .../math/bits/__test__/getBit.test.js | 23 ++++++++++++ .../math/bits/__test__/setBit.test.js | 15 ++++++++ .../math/bits/__test__/updateBit.test.js | 19 ++++++++++ src/algorithms/math/bits/clearBit.js | 10 +++++ src/algorithms/math/bits/getBit.js | 8 ++++ src/algorithms/math/bits/setBit.js | 8 ++++ src/algorithms/math/bits/updateBit.js | 16 ++++++++ 10 files changed, 152 insertions(+) create mode 100644 src/algorithms/math/bits/README.md create mode 100644 src/algorithms/math/bits/__test__/clearBit.test.js create mode 100644 src/algorithms/math/bits/__test__/getBit.test.js create mode 100644 src/algorithms/math/bits/__test__/setBit.test.js create mode 100644 src/algorithms/math/bits/__test__/updateBit.test.js create mode 100644 src/algorithms/math/bits/clearBit.js create mode 100644 src/algorithms/math/bits/getBit.js create mode 100644 src/algorithms/math/bits/setBit.js create mode 100644 src/algorithms/math/bits/updateBit.js diff --git a/README.md b/README.md index 088005fec9..b46717ec25 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ a set of rules that precisely define a sequence of operations. ### Algorithms by Topic * **Math** + * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits * `B` [Factorial](src/algorithms/math/factorial) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) diff --git a/src/algorithms/math/bits/README.md b/src/algorithms/math/bits/README.md new file mode 100644 index 0000000000..b56b06cbd8 --- /dev/null +++ b/src/algorithms/math/bits/README.md @@ -0,0 +1,37 @@ +# Bit Manipulation + +#### Get Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Then we perform `AND` operation +that clears all bits from the original number except the +`bitPosition` one. Then we compare the result with zero. If +result is zero that would mean that original number has `0` at +position `bitPosition`. + +> See `getBit` function for further details. + +#### Set Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Then we perform `OR` operation +that sets specific bit into `1` but it does not affect on +other bits of the number. + +> See `setBit` function for further details. + +#### Clear Bit + +This method shifts `1` over by `bitPosition` bits, creating a +value that looks like `00100`. Than it inverts this mask to get +the number that looks like `11011`. Then `AND` operation is +being applied to both the number and the mask. That operation +unsets the bit. + +> See `clearBit` function for further details. + +#### Update Bit + +This method is a combination of "Clear Bit" and "Set Bit" methods. + +> See `updateBit` function for further details. diff --git a/src/algorithms/math/bits/__test__/clearBit.test.js b/src/algorithms/math/bits/__test__/clearBit.test.js new file mode 100644 index 0000000000..2d758779cd --- /dev/null +++ b/src/algorithms/math/bits/__test__/clearBit.test.js @@ -0,0 +1,15 @@ +import clearBit from '../clearBit'; + +describe('clearBit', () => { + it('should clear bit at specific position', () => { + // 1 = 0b0001 + expect(clearBit(1, 0)).toBe(0); + expect(clearBit(1, 1)).toBe(1); + expect(clearBit(1, 2)).toBe(1); + + // 10 = 0b1010 + expect(clearBit(10, 0)).toBe(10); + expect(clearBit(10, 1)).toBe(8); + expect(clearBit(10, 3)).toBe(2); + }); +}); diff --git a/src/algorithms/math/bits/__test__/getBit.test.js b/src/algorithms/math/bits/__test__/getBit.test.js new file mode 100644 index 0000000000..3a7026f2d9 --- /dev/null +++ b/src/algorithms/math/bits/__test__/getBit.test.js @@ -0,0 +1,23 @@ +import getBit from '../getBit'; + +describe('getBit', () => { + it('should get bit at specific position', () => { + // 1 = 0b0001 + expect(getBit(1, 0)).toBe(1); + expect(getBit(1, 1)).toBe(0); + + // 2 = 0b0010 + expect(getBit(2, 0)).toBe(0); + expect(getBit(2, 1)).toBe(1); + + // 3 = 0b0011 + expect(getBit(3, 0)).toBe(1); + expect(getBit(3, 1)).toBe(1); + + // 10 = 0b1010 + expect(getBit(10, 0)).toBe(0); + expect(getBit(10, 1)).toBe(1); + expect(getBit(10, 2)).toBe(0); + expect(getBit(10, 3)).toBe(1); + }); +}); diff --git a/src/algorithms/math/bits/__test__/setBit.test.js b/src/algorithms/math/bits/__test__/setBit.test.js new file mode 100644 index 0000000000..d53d60c746 --- /dev/null +++ b/src/algorithms/math/bits/__test__/setBit.test.js @@ -0,0 +1,15 @@ +import setBit from '../setBit'; + +describe('setBit', () => { + it('should set bit at specific position', () => { + // 1 = 0b0001 + expect(setBit(1, 0)).toBe(1); + expect(setBit(1, 1)).toBe(3); + expect(setBit(1, 2)).toBe(5); + + // 10 = 0b1010 + expect(setBit(10, 0)).toBe(11); + expect(setBit(10, 1)).toBe(10); + expect(setBit(10, 2)).toBe(14); + }); +}); diff --git a/src/algorithms/math/bits/__test__/updateBit.test.js b/src/algorithms/math/bits/__test__/updateBit.test.js new file mode 100644 index 0000000000..e2ac2db005 --- /dev/null +++ b/src/algorithms/math/bits/__test__/updateBit.test.js @@ -0,0 +1,19 @@ +import updateBit from '../updateBit'; + +describe('updateBit', () => { + it('should update bit at specific position', () => { + // 1 = 0b0001 + expect(updateBit(1, 0, 1)).toBe(1); + expect(updateBit(1, 0, 0)).toBe(0); + expect(updateBit(1, 1, 1)).toBe(3); + expect(updateBit(1, 2, 1)).toBe(5); + + // 10 = 0b1010 + expect(updateBit(10, 0, 1)).toBe(11); + expect(updateBit(10, 0, 0)).toBe(10); + expect(updateBit(10, 1, 1)).toBe(10); + expect(updateBit(10, 1, 0)).toBe(8); + expect(updateBit(10, 2, 1)).toBe(14); + expect(updateBit(10, 2, 0)).toBe(10); + }); +}); diff --git a/src/algorithms/math/bits/clearBit.js b/src/algorithms/math/bits/clearBit.js new file mode 100644 index 0000000000..0329a0476d --- /dev/null +++ b/src/algorithms/math/bits/clearBit.js @@ -0,0 +1,10 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function clearBit(number, bitPosition) { + const mask = ~(1 << bitPosition); + + return number & mask; +} diff --git a/src/algorithms/math/bits/getBit.js b/src/algorithms/math/bits/getBit.js new file mode 100644 index 0000000000..a99ce7d53b --- /dev/null +++ b/src/algorithms/math/bits/getBit.js @@ -0,0 +1,8 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function getBit(number, bitPosition) { + return (number & (1 << bitPosition)) === 0 ? 0 : 1; +} diff --git a/src/algorithms/math/bits/setBit.js b/src/algorithms/math/bits/setBit.js new file mode 100644 index 0000000000..c574ac692e --- /dev/null +++ b/src/algorithms/math/bits/setBit.js @@ -0,0 +1,8 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @return {number} + */ +export default function setBit(number, bitPosition) { + return number | (1 << bitPosition); +} diff --git a/src/algorithms/math/bits/updateBit.js b/src/algorithms/math/bits/updateBit.js new file mode 100644 index 0000000000..b338cd0eab --- /dev/null +++ b/src/algorithms/math/bits/updateBit.js @@ -0,0 +1,16 @@ +/** + * @param {number} number + * @param {number} bitPosition - zero based. + * @param {number} bitValue - 0 or 1. + * @return {number} + */ +export default function updateBit(number, bitPosition, bitValue) { + // Normalized bit value. + const bitValueNormalized = bitValue ? 1 : 0; + + // Init clear mask. + const clearMask = ~(1 << bitPosition); + + // Cleat bit value and then set it up to required value. + return (number & clearMask) | (bitValueNormalized << bitPosition); +} From c26820325917f05e80ff547797e00f9ade33ff9c Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 27 Jun 2018 17:33:16 +0300 Subject: [PATCH 38/44] Add more bit manipulation functions. --- README.md | 2 +- src/algorithms/math/bits/README.md | 34 +++++++++++++++++++ .../math/bits/__test__/divideByTwo.test.js | 12 +++++++ .../math/bits/__test__/multiplyByTwo.test.js | 12 +++++++ src/algorithms/math/bits/divideByTwo.js | 7 ++++ src/algorithms/math/bits/multiplyByTwo.js | 7 ++++ 6 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/math/bits/__test__/divideByTwo.test.js create mode 100644 src/algorithms/math/bits/__test__/multiplyByTwo.test.js create mode 100644 src/algorithms/math/bits/divideByTwo.js create mode 100644 src/algorithms/math/bits/multiplyByTwo.js diff --git a/README.md b/README.md index b46717ec25..c8ec1a6dbf 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ a set of rules that precisely define a sequence of operations. ### Algorithms by Topic * **Math** - * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits + * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two etc. * `B` [Factorial](src/algorithms/math/factorial) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) diff --git a/src/algorithms/math/bits/README.md b/src/algorithms/math/bits/README.md index b56b06cbd8..7212fdb4b6 100644 --- a/src/algorithms/math/bits/README.md +++ b/src/algorithms/math/bits/README.md @@ -35,3 +35,37 @@ unsets the bit. This method is a combination of "Clear Bit" and "Set Bit" methods. > See `updateBit` function for further details. + +#### Multiply By Two + +This method shifts original number by one bit to the left. +Thus all binary number components (powers of two) are being +multiplying by two and thus the number itself is being +multiplied by two. + +``` +Before the shift +Number: 0b0101 = 5 +Powers of two: 0 + 2^2 + 0 + 2^0 + +After the shift +Number: 0b1010 = 10 +Powers of two: 2^3 + 0 + 2^1 + 0 +``` + +#### Divide By Two + +This method shifts original number by one bit to the right. +Thus all binary number components (powers of two) are being +divided by two and thus the number itself is being +divided by two without remainder. + +``` +Before the shift +Number: 0b0101 = 5 +Powers of two: 0 + 2^2 + 0 + 2^0 + +After the shift +Number: 0b0010 = 2 +Powers of two: 0 + 0 + 2^1 + 0 +``` diff --git a/src/algorithms/math/bits/__test__/divideByTwo.test.js b/src/algorithms/math/bits/__test__/divideByTwo.test.js new file mode 100644 index 0000000000..ec829367ec --- /dev/null +++ b/src/algorithms/math/bits/__test__/divideByTwo.test.js @@ -0,0 +1,12 @@ +import divideByTwo from '../divideByTwo'; + +describe('divideByTwo', () => { + it('should divide numbers by two using bitwise operations', () => { + expect(divideByTwo(0)).toBe(0); + expect(divideByTwo(1)).toBe(0); + expect(divideByTwo(3)).toBe(1); + expect(divideByTwo(10)).toBe(5); + expect(divideByTwo(17)).toBe(8); + expect(divideByTwo(125)).toBe(62); + }); +}); diff --git a/src/algorithms/math/bits/__test__/multiplyByTwo.test.js b/src/algorithms/math/bits/__test__/multiplyByTwo.test.js new file mode 100644 index 0000000000..07934c57ba --- /dev/null +++ b/src/algorithms/math/bits/__test__/multiplyByTwo.test.js @@ -0,0 +1,12 @@ +import multiplyByTwo from '../multiplyByTwo'; + +describe('multiplyByTwo', () => { + it('should multiply numbers by two using bitwise operations', () => { + expect(multiplyByTwo(0)).toBe(0); + expect(multiplyByTwo(1)).toBe(2); + expect(multiplyByTwo(3)).toBe(6); + expect(multiplyByTwo(10)).toBe(20); + expect(multiplyByTwo(17)).toBe(34); + expect(multiplyByTwo(125)).toBe(250); + }); +}); diff --git a/src/algorithms/math/bits/divideByTwo.js b/src/algorithms/math/bits/divideByTwo.js new file mode 100644 index 0000000000..359bef9d59 --- /dev/null +++ b/src/algorithms/math/bits/divideByTwo.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {number} + */ +export default function divideByTwo(number) { + return number >> 1; +} diff --git a/src/algorithms/math/bits/multiplyByTwo.js b/src/algorithms/math/bits/multiplyByTwo.js new file mode 100644 index 0000000000..3e52544d29 --- /dev/null +++ b/src/algorithms/math/bits/multiplyByTwo.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {number} + */ +export default function multiplyByTwo(number) { + return number << 1; +} From 933848b2155ab5d9c03ac5701e529a41bd3a18b7 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 27 Jun 2018 18:05:18 +0300 Subject: [PATCH 39/44] Add more bit manipulation functions. --- README.md | 2 +- src/algorithms/math/bits/README.md | 28 +++++++++++++++++++ .../math/bits/__test__/switchSign.test.js | 13 +++++++++ src/algorithms/math/bits/switchSign.js | 8 ++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/math/bits/__test__/switchSign.test.js create mode 100644 src/algorithms/math/bits/switchSign.js diff --git a/README.md b/README.md index c8ec1a6dbf..c1cd52a1d4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ a set of rules that precisely define a sequence of operations. ### Algorithms by Topic * **Math** - * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two etc. + * `B` [Bit Manipulation](src/algorithms/math/bits) - set/get/update/clear bits, multiplication/division by two, make negative etc. * `B` [Factorial](src/algorithms/math/factorial) * `B` [Fibonacci Number](src/algorithms/math/fibonacci) * `B` [Primality Test](src/algorithms/math/primality-test) (trial division method) diff --git a/src/algorithms/math/bits/README.md b/src/algorithms/math/bits/README.md index 7212fdb4b6..736cbebf1b 100644 --- a/src/algorithms/math/bits/README.md +++ b/src/algorithms/math/bits/README.md @@ -53,6 +53,8 @@ Number: 0b1010 = 10 Powers of two: 2^3 + 0 + 2^1 + 0 ``` +> See `multiplyByTwo` function for further details. + #### Divide By Two This method shifts original number by one bit to the right. @@ -69,3 +71,29 @@ After the shift Number: 0b0010 = 2 Powers of two: 0 + 0 + 2^1 + 0 ``` + +> See `divideByTwo` function for further details. + +#### Switch Sign + +This method make positive numbers to be negative and backwards. +To do so it uses "Twos Complement" approach which does it by +inverting all of the bits of the number and adding 1 to it. + +``` +1101 -3 +1110 -2 +1111 -1 +0000 0 +0001 1 +0010 2 +0011 3 +``` + +> See `switchSign` function for further details. + +## References + +- [Bit Manipulation on YouTube](https://www.youtube.com/watch?v=NLKQEOgBAnw&t=0s&index=28&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) +- [Negative Numbers in binary on YouTube](https://www.youtube.com/watch?v=4qH4unVtJkE&t=0s&index=30&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8) +- [Bit Hacks on stanford.edu](https://graphics.stanford.edu/~seander/bithacks.html) diff --git a/src/algorithms/math/bits/__test__/switchSign.test.js b/src/algorithms/math/bits/__test__/switchSign.test.js new file mode 100644 index 0000000000..af3f36df5e --- /dev/null +++ b/src/algorithms/math/bits/__test__/switchSign.test.js @@ -0,0 +1,13 @@ +import switchSign from '../switchSign'; + +describe('switchSign', () => { + it('should switch the sign of the number using twos complement approach', () => { + expect(switchSign(0)).toBe(0); + expect(switchSign(1)).toBe(-1); + expect(switchSign(-1)).toBe(1); + expect(switchSign(32)).toBe(-32); + expect(switchSign(-32)).toBe(32); + expect(switchSign(23)).toBe(-23); + expect(switchSign(-23)).toBe(23); + }); +}); diff --git a/src/algorithms/math/bits/switchSign.js b/src/algorithms/math/bits/switchSign.js new file mode 100644 index 0000000000..e38ec487ef --- /dev/null +++ b/src/algorithms/math/bits/switchSign.js @@ -0,0 +1,8 @@ +/** + * Switch the sign of the number using "Twos Complement" approach. + * @param {number} number + * @return {number} + */ +export default function switchSign(number) { + return ~number + 1; +} From 55ecc0b31371b8abfce08a870b0339e121784a57 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Wed, 27 Jun 2018 18:59:25 +0300 Subject: [PATCH 40/44] Fix typo. --- src/algorithms/math/bits/updateBit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/math/bits/updateBit.js b/src/algorithms/math/bits/updateBit.js index b338cd0eab..f56834a3ea 100644 --- a/src/algorithms/math/bits/updateBit.js +++ b/src/algorithms/math/bits/updateBit.js @@ -11,6 +11,6 @@ export default function updateBit(number, bitPosition, bitValue) { // Init clear mask. const clearMask = ~(1 << bitPosition); - // Cleat bit value and then set it up to required value. + // Clear bit value and then set it up to required value. return (number & clearMask) | (bitValueNormalized << bitPosition); } From e5a06e654bebfe44bb63938a55eaebd960fb1378 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 28 Jun 2018 13:46:26 +0300 Subject: [PATCH 41/44] Simplify combineWithoutRepetitions function. --- .../combinations/combineWithoutRepetitions.js | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/algorithms/sets/combinations/combineWithoutRepetitions.js b/src/algorithms/sets/combinations/combineWithoutRepetitions.js index 15678ee830..a6f50ec073 100644 --- a/src/algorithms/sets/combinations/combineWithoutRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithoutRepetitions.js @@ -1,37 +1,29 @@ /** * @param {*[]} comboOptions * @param {number} comboLength - * @param {*[][]} combos - * @param {*[]} currentCombo * @return {*[]} */ -function combineRecursively(comboOptions, comboLength, combos = [], currentCombo = []) { - if (comboLength === 0) { - combos.push(currentCombo); - - return combos; +export default function combineWithoutRepetitions(comboOptions, comboLength) { + if (comboLength === 1) { + return comboOptions.map(comboOption => [comboOption]); } + const combos = []; + + // Eliminate characters one by one and concatenate them to + // combinations of smaller lengths.s for (let letterIndex = 0; letterIndex <= (comboOptions.length - comboLength); letterIndex += 1) { - const letter = comboOptions[letterIndex]; - const restCombinationOptions = comboOptions.slice(letterIndex + 1); + const currentLetter = comboOptions[letterIndex]; - combineRecursively( - restCombinationOptions, + const smallerCombos = combineWithoutRepetitions( + comboOptions.slice(letterIndex + 1), comboLength - 1, - combos, - currentCombo.concat([letter]), ); + + smallerCombos.forEach((smallerCombo) => { + combos.push([currentLetter].concat(smallerCombo)); + }); } return combos; } - -/** - * @param {*[]} combinationOptions - * @param {number} combinationLength - * @return {*[]} - */ -export default function combineWithoutRepetitions(combinationOptions, combinationLength) { - return combineRecursively(combinationOptions, combinationLength); -} From 65f08db5deb8737ee0a9cf89518c9a99c1fccfb0 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 28 Jun 2018 14:05:58 +0300 Subject: [PATCH 42/44] Simplify combineWithRepetitions function. --- .../combinations/combineWithRepetitions.js | 44 ++++++++----------- .../combinations/combineWithoutRepetitions.js | 11 ++--- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/algorithms/sets/combinations/combineWithRepetitions.js b/src/algorithms/sets/combinations/combineWithRepetitions.js index 0d2ef3c167..a95d285716 100644 --- a/src/algorithms/sets/combinations/combineWithRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithRepetitions.js @@ -1,38 +1,30 @@ /** - * @param {*[]} combinationOptions - * @param {number} combinationLength + * @param {*[]} comboOptions + * @param {number} comboLength * @return {*[]} */ - -export default function combineWithRepetitions(combinationOptions, combinationLength) { - // If combination length equal to 0 then return empty combination. - if (combinationLength === 0) { - return [[]]; - } - - // If combination options are empty then return "no-combinations" array. - if (combinationOptions.length === 0) { - return []; +export default function combineWithRepetitions(comboOptions, comboLength) { + if (comboLength === 1) { + return comboOptions.map(comboOption => [comboOption]); } // Init combinations array. const combos = []; - // Find all shorter combinations and attach head to each of those. - const headCombo = [combinationOptions[0]]; - const shorterCombos = combineWithRepetitions(combinationOptions, combinationLength - 1); + // Eliminate characters one by one and concatenate them to + // combinations of smaller lengths. + for (let optionIndex = 0; optionIndex < comboOptions.length; optionIndex += 1) { + const currentOption = comboOptions[optionIndex]; - for (let combinationIndex = 0; combinationIndex < shorterCombos.length; combinationIndex += 1) { - const combo = headCombo.concat(shorterCombos[combinationIndex]); - combos.push(combo); - } + const smallerCombos = combineWithRepetitions( + comboOptions.slice(optionIndex), + comboLength - 1, + ); - // Let's shift head to the right and calculate all the rest combinations. - const combinationsWithoutHead = combineWithRepetitions( - combinationOptions.slice(1), - combinationLength, - ); + smallerCombos.forEach((smallerCombo) => { + combos.push([currentOption].concat(smallerCombo)); + }); + } - // Join all combinations and return them. - return combos.concat(combinationsWithoutHead); + return combos; } diff --git a/src/algorithms/sets/combinations/combineWithoutRepetitions.js b/src/algorithms/sets/combinations/combineWithoutRepetitions.js index a6f50ec073..8f712b5126 100644 --- a/src/algorithms/sets/combinations/combineWithoutRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithoutRepetitions.js @@ -8,20 +8,21 @@ export default function combineWithoutRepetitions(comboOptions, comboLength) { return comboOptions.map(comboOption => [comboOption]); } + // Init combinations array. const combos = []; // Eliminate characters one by one and concatenate them to - // combinations of smaller lengths.s - for (let letterIndex = 0; letterIndex <= (comboOptions.length - comboLength); letterIndex += 1) { - const currentLetter = comboOptions[letterIndex]; + // combinations of smaller lengths. + for (let optionIndex = 0; optionIndex <= (comboOptions.length - comboLength); optionIndex += 1) { + const currentOption = comboOptions[optionIndex]; const smallerCombos = combineWithoutRepetitions( - comboOptions.slice(letterIndex + 1), + comboOptions.slice(optionIndex + 1), comboLength - 1, ); smallerCombos.forEach((smallerCombo) => { - combos.push([currentLetter].concat(smallerCombo)); + combos.push([currentOption].concat(smallerCombo)); }); } From c5ed81d85e2c131df3112a5a02d7946786d5c190 Mon Sep 17 00:00:00 2001 From: m-maksyutin Date: Thu, 28 Jun 2018 21:03:31 +0300 Subject: [PATCH 43/44] Add recursive factorial function (#85) * Fix LinkedList * Fix the prepend method for the LinkedList * Fix the remove method for the MinHeap * Correct a comment * Fix BST removal method * Fix the findEdge method of the graph * Fix the value returned by DisjointSet union * Add recursive factorial function --- .../factorial/__test__/factorialRecursive.test.js | 11 +++++++++++ src/algorithms/math/factorial/factorialRecursive.js | 7 +++++++ 2 files changed, 18 insertions(+) create mode 100644 src/algorithms/math/factorial/__test__/factorialRecursive.test.js create mode 100644 src/algorithms/math/factorial/factorialRecursive.js diff --git a/src/algorithms/math/factorial/__test__/factorialRecursive.test.js b/src/algorithms/math/factorial/__test__/factorialRecursive.test.js new file mode 100644 index 0000000000..9029faee0a --- /dev/null +++ b/src/algorithms/math/factorial/__test__/factorialRecursive.test.js @@ -0,0 +1,11 @@ +import factorialRecursive from '../factorialRecursive'; + +describe('factorialRecursive', () => { + it('should calculate factorial', () => { + expect(factorialRecursive(0)).toBe(1); + expect(factorialRecursive(1)).toBe(1); + expect(factorialRecursive(5)).toBe(120); + expect(factorialRecursive(8)).toBe(40320); + expect(factorialRecursive(10)).toBe(3628800); + }); +}); diff --git a/src/algorithms/math/factorial/factorialRecursive.js b/src/algorithms/math/factorial/factorialRecursive.js new file mode 100644 index 0000000000..e2b4aec6c9 --- /dev/null +++ b/src/algorithms/math/factorial/factorialRecursive.js @@ -0,0 +1,7 @@ +/** + * @param {number} number + * @return {number} + */ +export default function factorialRecursive(number) { + return number > 1 ? number * factorialRecursive(number - 1) : 1; +} From db7ab9e299fb483e150809b89bc16f7ca52fcf7b Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Thu, 28 Jun 2018 21:28:50 +0300 Subject: [PATCH 44/44] Simplify permutateWithRepetitions algorithm. --- .../combinations/combineWithRepetitions.js | 6 +- .../combinations/combineWithoutRepetitions.js | 6 +- .../__test__/permutateWithRepetitions.test.js | 3 - .../permutateWithRepetitionsRecursive.test.js | 55 ------------------- .../permutations/permutateWithRepetitions.js | 52 +++++++----------- .../permutateWithRepetitionsRecursive.js | 37 ------------- 6 files changed, 24 insertions(+), 135 deletions(-) delete mode 100644 src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js delete mode 100644 src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js diff --git a/src/algorithms/sets/combinations/combineWithRepetitions.js b/src/algorithms/sets/combinations/combineWithRepetitions.js index a95d285716..8a743289f3 100644 --- a/src/algorithms/sets/combinations/combineWithRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithRepetitions.js @@ -13,9 +13,7 @@ export default function combineWithRepetitions(comboOptions, comboLength) { // Eliminate characters one by one and concatenate them to // combinations of smaller lengths. - for (let optionIndex = 0; optionIndex < comboOptions.length; optionIndex += 1) { - const currentOption = comboOptions[optionIndex]; - + comboOptions.forEach((currentOption, optionIndex) => { const smallerCombos = combineWithRepetitions( comboOptions.slice(optionIndex), comboLength - 1, @@ -24,7 +22,7 @@ export default function combineWithRepetitions(comboOptions, comboLength) { smallerCombos.forEach((smallerCombo) => { combos.push([currentOption].concat(smallerCombo)); }); - } + }); return combos; } diff --git a/src/algorithms/sets/combinations/combineWithoutRepetitions.js b/src/algorithms/sets/combinations/combineWithoutRepetitions.js index 8f712b5126..56c1e8fe48 100644 --- a/src/algorithms/sets/combinations/combineWithoutRepetitions.js +++ b/src/algorithms/sets/combinations/combineWithoutRepetitions.js @@ -13,9 +13,7 @@ export default function combineWithoutRepetitions(comboOptions, comboLength) { // Eliminate characters one by one and concatenate them to // combinations of smaller lengths. - for (let optionIndex = 0; optionIndex <= (comboOptions.length - comboLength); optionIndex += 1) { - const currentOption = comboOptions[optionIndex]; - + comboOptions.forEach((currentOption, optionIndex) => { const smallerCombos = combineWithoutRepetitions( comboOptions.slice(optionIndex + 1), comboLength - 1, @@ -24,7 +22,7 @@ export default function combineWithoutRepetitions(comboOptions, comboLength) { smallerCombos.forEach((smallerCombo) => { combos.push([currentOption].concat(smallerCombo)); }); - } + }); return combos; } diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js index 2984b7c9e3..0d53def1ae 100644 --- a/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js +++ b/src/algorithms/sets/permutations/__test__/permutateWithRepetitions.test.js @@ -2,9 +2,6 @@ import permutateWithRepetitions from '../permutateWithRepetitions'; describe('permutateWithRepetitions', () => { it('should permutate string with repetition', () => { - const permutations0 = permutateWithRepetitions([]); - expect(permutations0).toEqual([]); - const permutations1 = permutateWithRepetitions(['A']); expect(permutations1).toEqual([ ['A'], diff --git a/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js b/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js deleted file mode 100644 index 62b412320d..0000000000 --- a/src/algorithms/sets/permutations/__test__/permutateWithRepetitionsRecursive.test.js +++ /dev/null @@ -1,55 +0,0 @@ -import permutateWithRepetitionsRecursive from '../permutateWithRepetitionsRecursive'; - -describe('permutateWithRepetitionsRecursive', () => { - it('should permutate string with repetition', () => { - const permutations0 = permutateWithRepetitionsRecursive([]); - expect(permutations0).toEqual([]); - - const permutations1 = permutateWithRepetitionsRecursive(['A']); - expect(permutations1).toEqual([ - ['A'], - ]); - - const permutations2 = permutateWithRepetitionsRecursive(['A', 'B']); - expect(permutations2).toEqual([ - ['A', 'A'], - ['A', 'B'], - ['B', 'A'], - ['B', 'B'], - ]); - - const permutations3 = permutateWithRepetitionsRecursive(['A', 'B', 'C']); - expect(permutations3).toEqual([ - ['A', 'A', 'A'], - ['A', 'A', 'B'], - ['A', 'A', 'C'], - ['A', 'B', 'A'], - ['A', 'B', 'B'], - ['A', 'B', 'C'], - ['A', 'C', 'A'], - ['A', 'C', 'B'], - ['A', 'C', 'C'], - ['B', 'A', 'A'], - ['B', 'A', 'B'], - ['B', 'A', 'C'], - ['B', 'B', 'A'], - ['B', 'B', 'B'], - ['B', 'B', 'C'], - ['B', 'C', 'A'], - ['B', 'C', 'B'], - ['B', 'C', 'C'], - ['C', 'A', 'A'], - ['C', 'A', 'B'], - ['C', 'A', 'C'], - ['C', 'B', 'A'], - ['C', 'B', 'B'], - ['C', 'B', 'C'], - ['C', 'C', 'A'], - ['C', 'C', 'B'], - ['C', 'C', 'C'], - ]); - - const permutations4 = permutateWithRepetitionsRecursive(['A', 'B', 'C', 'D']); - expect(permutations4.length).toBe(4 * 4 * 4 * 4); - }); -}); diff --git a/src/algorithms/sets/permutations/permutateWithRepetitions.js b/src/algorithms/sets/permutations/permutateWithRepetitions.js index 25d6fcafa4..90502d29f6 100644 --- a/src/algorithms/sets/permutations/permutateWithRepetitions.js +++ b/src/algorithms/sets/permutations/permutateWithRepetitions.js @@ -1,42 +1,30 @@ /** * @param {*[]} permutationOptions + * @param {number} permutationLength * @return {*[]} */ -export default function permutateWithRepetitions(permutationOptions) { - // There is no permutations for empty array. - if (!permutationOptions || permutationOptions.length === 0) { - return []; +export default function permutateWithRepetitions( + permutationOptions, + permutationLength = permutationOptions.length, +) { + if (permutationLength === 1) { + return permutationOptions.map(permutationOption => [permutationOption]); } - // There is only one permutation for the 1-element array. - if (permutationOptions.length === 1) { - return [permutationOptions]; - } - - // Let's create initial set of permutations. - let previousPermutations = permutationOptions.map(option => [option]); - let currentPermutations = []; - let permutationSize = 1; - - // While the size of each permutation is less then or equal to options length... - while (permutationSize < permutationOptions.length) { - // Reset all current permutations. - currentPermutations = []; + // Init permutations array. + const permutations = []; - for (let permIndex = 0; permIndex < previousPermutations.length; permIndex += 1) { - for (let optionIndex = 0; optionIndex < permutationOptions.length; optionIndex += 1) { - let currentPermutation = previousPermutations[permIndex]; - currentPermutation = currentPermutation.concat([permutationOptions[optionIndex]]); - currentPermutations.push(currentPermutation); - } - } + // Go through all options and join it to the smaller permutations. + permutationOptions.forEach((currentOption) => { + const smallerPermutations = permutateWithRepetitions( + permutationOptions, + permutationLength - 1, + ); - // Make current permutations to be the previous ones. - previousPermutations = currentPermutations.slice(0); - - // Increase permutation size counter. - permutationSize += 1; - } + smallerPermutations.forEach((smallerPermutation) => { + permutations.push([currentOption].concat(smallerPermutation)); + }); + }); - return currentPermutations; + return permutations; } diff --git a/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js b/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js deleted file mode 100644 index f379c7cefd..0000000000 --- a/src/algorithms/sets/permutations/permutateWithRepetitionsRecursive.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {*[]} permutationOptions - * @param {number} permutationLength - * @param {*[]} currentPermutation - * @param {*[][]} permutations - * @return {*[]} - */ -export default function permutateWithRepetitionsRecursive( - permutationOptions, - permutationLength = permutationOptions.length || 0, - currentPermutation = [], - permutations = [], -) { - // If initial options are null or empty then return empty array. - if (!permutationOptions || !permutationOptions.length) { - return []; - } - - // If no more iterations required then add current permutation to permutations array. - if (permutationLength === 0) { - permutations.push(currentPermutation); - - return permutations; - } - - // Recursively find permutations and store in permutations array. - permutationOptions.forEach((permutationOption) => { - permutateWithRepetitionsRecursive( - permutationOptions, - permutationLength - 1, - currentPermutation.concat([permutationOption]), - permutations, - ); - }); - - return permutations; -}