├── Algorithms └── BoyerMoore.js ├── Bit Manipulation ├── BItwiseMultiply.js ├── BitwiseAdd.js ├── BitwiseDivide.js ├── BitwiseDividePositive.js ├── BitwiseNegate.js ├── BitwiseSubtract.js └── isCharactersUnique.js ├── Data Structure Design ├── ConstantTimeInsertDeleteSearchRandom.js └── SetWithPrimitives.js ├── Data Structures ├── AVLTree.js ├── AdjacencyMatrix.js ├── BinaryTree.js ├── CustomSet.js ├── DiGraph.js ├── DirectedGraph.js ├── DoublyLinkedList.js ├── Graph.js ├── GraphClass.js ├── LRU.js ├── LinkedList.js ├── MaxHeap.js ├── MinHeap.js ├── Queue.js ├── Set.js ├── Stack.js ├── Tree.js ├── Trie.js └── UndirectedGraph.js ├── Design Patterns ├── Decorator.js ├── Facade.js ├── Factory.js ├── Observer.js ├── RevealingModule.js └── Singleton.js ├── Examples └── LocalStorage.js ├── Graphs └── TopologicalSort.js ├── Problems ├── Arrays │ ├── BoyerMooreVote.js │ ├── arraySlice.js │ ├── commonElements.js │ ├── duplicatesInArray.js │ ├── findLargestProductItems.js │ ├── findSum.js │ ├── findSumBetter.js │ ├── majorityElement.js │ ├── maxProfit.js │ ├── maxProfitMutipleTransactions.js │ ├── maxSubarray.js │ ├── medianOfTwoSortedArray.js │ ├── missingNumber.js │ ├── partition.js │ ├── pigeonHole.js │ ├── subsets.js │ └── threeSum.js ├── Dynamic Programming │ ├── .ipynb_checkpoints │ │ └── Dynamic Programming-checkpoint.ipynb │ ├── Dynamic Programming.ipynb │ ├── countCoinWays.js │ ├── knapsackDP.js │ ├── knapsackNaiive.js │ └── longestString.js ├── Heaps │ ├── MedianHeap.js │ ├── getKthBiggestElement.js │ └── getKthSmallestElement.js ├── LinkedLists │ ├── deleteDuplicates.js │ ├── deleteNode.js │ ├── findMergePoint.js │ ├── findMiddlePoint.js │ ├── isPalindrome.js │ ├── linkedListToString.js │ ├── mergeIteratively.js │ ├── mergeRecursively.js │ ├── reverseLinkedList.js │ └── sortLinkedList.js ├── MultiDimensionalArrays │ ├── mazePathFinder.js │ ├── rotateMatrix.js │ ├── spiralPrint.js │ └── ticTacToeWinner.js ├── Numbers │ ├── allPrimesLessThanN.js │ ├── arrayNUglyNumbers.js │ ├── isPalindrome.js │ └── modularExponentiation.js ├── Recursion │ ├── base10ToBinary.js │ ├── flattenDictionary.js │ ├── isPalindromeRecursive.js │ └── permuteArray.js ├── SearchSort │ ├── arraySort.js │ ├── pigeonholeSort.js │ └── wordCount.js ├── StacksQueues │ ├── CashierQueue.js │ ├── QueueStack.js │ ├── SortableStack.js │ ├── StackQueue.js │ └── isParenthesisValid.js ├── Strings │ ├── KMP.js │ ├── compressString.js │ ├── convertToStringBaseX.js │ ├── hashCode.js │ ├── indexOf.js │ ├── isAnagram.js │ ├── isIsomorphic.js │ ├── longestCommonSequenceLength.js │ ├── longestCommonSequenceLengthDP.js │ ├── longestCommonSequenceString.js │ ├── longestCommonSequenceStringDP.js │ ├── maxSubArray.js │ ├── removeExtraSpaces.js │ ├── reverseString.js │ ├── reverseWords.js │ └── wordsIsRotation.js └── Trees │ ├── binaryTreeToArray.js │ ├── checkIfSubtree.js │ ├── createBSTFromArray.js │ ├── deepestLeft.js │ ├── deepestRight.js │ ├── findLowestCommonAncestor.js │ ├── getHeight.js │ ├── hasPathSum.js │ ├── invertTree.js │ ├── isMirrorTrees.js │ ├── isSameTree.js │ ├── isTreeUnival.js │ ├── maxDepth.js │ ├── minDepth.js │ ├── printKthLevels.js │ ├── rightSideView.js │ ├── sumOfLeftLeaves.js │ ├── sumOfRightLeaves.js │ └── upsideDownBinaryTree.js ├── README.md └── Strings └── base62Encode.js /Algorithms/BoyerMoore.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function boyerMoore(haystack, needle) { 3 | var badMatchTable = {}; 4 | var maxOffset = haystack.length - needle.length; 5 | var offset = 0; 6 | var last = needle.length - 1; 7 | var scan; 8 | 9 | if (last < 0) return 0 10 | 11 | // Generate the bad match table, which is the location of offsets 12 | // to jump forward when a comparison fails 13 | for (var i = 0; i < needle.length - 1; i++) { 14 | badMatchTable[needle[i]] = last - i; 15 | } 16 | 17 | // Now look for the needle 18 | while (offset <= maxOffset) { 19 | // Search right-to-left, checking to see if the current offset at 20 | // needle and haystack match. If they do, rewind 1, repeat, and if we 21 | // eventually match the first character, return the offset. 22 | for (scan = last; needle[scan] === haystack[scan + offset]; scan--) { 23 | if (scan === 0) { 24 | return offset; 25 | } 26 | } 27 | 28 | offset += badMatchTable[haystack[offset + last]] || last || 1; 29 | } 30 | 31 | return -1; 32 | } -------------------------------------------------------------------------------- /Bit Manipulation/BItwiseMultiply.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function BitwiseAdd(a, b) { 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | return a; 9 | } 10 | 11 | function BitwiseNegate(a) { 12 | return BitwiseAdd(~a, 1); 13 | } 14 | 15 | // Main 16 | function BitwiseMultiply(a, b) { 17 | var m = 1, 18 | c = 0; 19 | 20 | if (a < 0) { 21 | a = BitwiseNegate(a); 22 | b = BitwiseNegate(b); 23 | } 24 | 25 | while (a >= m && b) { 26 | if (a & m) { 27 | c = BitwiseAdd(b, c); 28 | } 29 | b = b << 1; 30 | m = m << 1; 31 | } 32 | return c; 33 | } 34 | 35 | console.log(BitwiseMultiply(4, 5)); // 20 -------------------------------------------------------------------------------- /Bit Manipulation/BitwiseAdd.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function BitwiseAdd(a, b){ 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | 9 | return a; 10 | } 11 | 12 | console.log(BitwiseAdd(4,5)); // prints 9 -------------------------------------------------------------------------------- /Bit Manipulation/BitwiseDivide.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function BitwiseAdd(a, b) { 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | 9 | return a; 10 | } 11 | 12 | function BitwiseNegate(a) { 13 | return BitwiseAdd(~a, 1); 14 | } 15 | 16 | function BitwiseSubtract(a, b) { 17 | return BitwiseAdd(a, BitwiseNegate(b)); 18 | } 19 | 20 | // Main 21 | function BitwiseDivide(a, b) { 22 | var c = 0, 23 | isNegative = 0; 24 | 25 | if (a < 0) { 26 | a = BitwiseNegate(a); // convert to positive 27 | isNegative = !isNegative; 28 | } 29 | 30 | if (b < 0) { 31 | b = BitwiseNegate(b); // convert to positive 32 | isNegative = !isNegative; 33 | } 34 | 35 | if (b != 0) { 36 | while (a >= b) { 37 | a = BitwiseSubtract(a, b); 38 | c++; 39 | } 40 | } 41 | 42 | if (isNegative) { 43 | c = BitwiseNegate(c); 44 | } 45 | 46 | return c; 47 | } 48 | 49 | console.log(BitwiseDivide(10, 2)); // 5 50 | console.log(BitwiseDivide(-10, 2)); // -5 51 | console.log(BitwiseDivide(-200, 4)); // -50 -------------------------------------------------------------------------------- /Bit Manipulation/BitwiseDividePositive.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function BitwiseAdd(a, b) { 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | 9 | return a; 10 | } 11 | 12 | function BitwiseNegate(a) { 13 | return BitwiseAdd(~a, 1); 14 | } 15 | 16 | function BitwiseSubtract(a, b) { 17 | return BitwiseAdd(a, BitwiseNegate(b)); 18 | } 19 | 20 | // Main 21 | function BitwiseDividePositive(a, b) { 22 | var c = 0; 23 | 24 | if (b != 0) { 25 | while (a >= b) { 26 | a = BitwiseSubtract(a, b); 27 | c++; 28 | } 29 | } 30 | return c; 31 | } 32 | 33 | console.log(BitwiseDividePositive(10, 2)); // 5 -------------------------------------------------------------------------------- /Bit Manipulation/BitwiseNegate.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function BitwiseAdd(a, b){ 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | 9 | return a; 10 | } 11 | 12 | // Main 13 | function BitwiseNegate(a) { 14 | return BitwiseAdd(~a,1); 15 | } 16 | 17 | console.log(BitwiseNegate(9)); // -9 18 | // negation with itself gives back original 19 | console.log(BitwiseNegate(BitwiseNegate(9))); // 9 -------------------------------------------------------------------------------- /Bit Manipulation/BitwiseSubtract.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function BitwiseAdd(a, b) { 3 | while (b != 0) { 4 | var carry = (a & b); 5 | a = a ^ b; 6 | b = carry << 1; 7 | } 8 | 9 | return a; 10 | } 11 | 12 | function BitwiseNegate(a) { 13 | return BitwiseAdd(~a, 1); 14 | } 15 | 16 | // Main 17 | function BitwiseSubtract(a, b) { 18 | return BitwiseAdd(a, BitwiseNegate(b)); 19 | } 20 | 21 | console.log(BitwiseSubtract(5, 4)); // prints 1 -------------------------------------------------------------------------------- /Bit Manipulation/isCharactersUnique.js: -------------------------------------------------------------------------------- 1 | function isCharactersUnique(str) { 2 | // An integer to store presence/absence 3 | // of 26 characters using its 32 bits. 4 | var checker = 0; 5 | 6 | for (var i = 0, strLength = str.length; i < strLength; i++) { 7 | var val = (str.charCodeAt(i) - 'a'.charCodeAt(0)); 8 | 9 | // If bit corresponding to current 10 | // character is already set 11 | if ((checker & (1 << val)) > 0) 12 | return false; 13 | 14 | // set bit in checker 15 | checker |= (1 << val); 16 | } 17 | 18 | return true; 19 | } 20 | 21 | console.log(isCharactersUnique('aabbcc')); // false 22 | // this is because 'a', 'b', and 'c' are repeated 23 | console.log(isCharactersUnique('abc')); // true 24 | // this is because no characters are repeated -------------------------------------------------------------------------------- /Data Structure Design/ConstantTimeInsertDeleteSearchRandom.js: -------------------------------------------------------------------------------- 1 | // Class that supports O(1) for insert, delete, search, random for integers 2 | function ConstantTimeInsertDeleteSearchRandom() { 3 | this.hash = {}; 4 | this.arr = []; 5 | } 6 | 7 | ConstantTimeInsertDeleteSearchRandom.prototype.insert = function(intVal) { 8 | this.arr.push(intVal); 9 | this.hash[intVal] = this.arr.length - 1; // store the index 10 | }; 11 | 12 | ConstantTimeInsertDeleteSearchRandom.prototype.delete = function(intVal) { 13 | let index = this.hash[intVal]; 14 | this.arr.splice(index, 1); 15 | delete this.hash[intVal]; 16 | }; 17 | 18 | ConstantTimeInsertDeleteSearchRandom.prototype.search = function(intVal) { 19 | return this.hash[intVal] != undefined; 20 | }; 21 | 22 | ConstantTimeInsertDeleteSearchRandom.prototype.random = function() { 23 | let randomIndex = Math.round(Math.random()*this.arr.length)-1; 24 | return this.arr[randomIndex]; 25 | }; -------------------------------------------------------------------------------- /Data Structure Design/SetWithPrimitives.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamEBae/jsds/2a40b28aa729d45dea5fc5fc49d68f3311ae2455/Data Structure Design/SetWithPrimitives.js -------------------------------------------------------------------------------- /Data Structures/AVLTree.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function AVLTree(n) { 3 | this.init(n); 4 | } 5 | 6 | AVLTree.prototype.init = function(value) { 7 | this.left = null; 8 | this.right = null; 9 | this.value = value; 10 | this.depth = 1; 11 | }; 12 | 13 | AVLTree.prototype.balance = function() { 14 | var ldepth = this.left == null ? 0 : this.left.depth; 15 | var rdepth = this.right == null ? 0 : this.right.depth; 16 | 17 | if (ldepth > rdepth + 1) { 18 | // LR or LL rotation 19 | var lldepth = this.left.left == null ? 0 : this.left.left.depth; 20 | var lrdepth = this.left.right == null ? 0 : this.left.right.depth; 21 | 22 | if (lldepth < lrdepth) { 23 | // LR rotation consists of a RR rotation of the left child 24 | this.left.rotateRR(); 25 | // plus a LL rotation of this node, which happens anyway 26 | } 27 | this.rotateLL(); 28 | } else if (ldepth + 1 < rdepth) { 29 | // RR or RL rorarion 30 | var rrdepth = this.right.right == null ? 0 : this.right.right.depth; 31 | var rldepth = this.right.left == null ? 0 : this.right.left.depth; 32 | 33 | if (rldepth > rrdepth) { 34 | // RR rotation consists of a LL rotation of the right child 35 | this.right.rotateLL(); 36 | // plus a RR rotation of this node, which happens anyway 37 | } 38 | this.rotateRR(); 39 | } 40 | }; 41 | 42 | AVLTree.prototype.rotateLL = function() { 43 | // the left side is too long => rotate from the left (_not_ leftwards) 44 | var valueBefore = this.value; 45 | var rightBefore = this.right; 46 | this.value = this.left.value; 47 | 48 | this.right = this.left; 49 | this.left = this.left.left; 50 | this.right.left = this.right.right; 51 | this.right.right = rightBefore; 52 | this.right.value = valueBefore; 53 | 54 | this.right.updateInNewLocation(); 55 | this.updateInNewLocation(); 56 | }; 57 | 58 | AVLTree.prototype.rotateRR = function() { 59 | // the right side is too long => rotate from the right (_not_ rightwards) 60 | var valueBefore = this.value; 61 | var leftBefore = this.left; 62 | this.value = this.right.value; 63 | 64 | this.left = this.right; 65 | this.right = this.right.right; 66 | this.left.right = this.left.left; 67 | this.left.left = leftBefore; 68 | this.left.value = valueBefore; 69 | 70 | this.left.updateInNewLocation(); 71 | this.updateInNewLocation(); 72 | }; 73 | 74 | AVLTree.prototype.updateInNewLocation = function() { 75 | this.getDepthFromChildren(); 76 | }; 77 | 78 | AVLTree.prototype.getDepthFromChildren = function() { 79 | this.depth = this.value == null ? 0 : 1; 80 | if (this.left != null) { 81 | this.depth = this.left.depth + 1; 82 | } 83 | if (this.right != null && this.depth <= this.right.depth) { 84 | this.depth = this.right.depth + 1; 85 | } 86 | }; 87 | 88 | AVLTree.prototype.compare = function(n1, n2) { 89 | if (n1 == n2) { 90 | return 0; 91 | } 92 | if (n1 < n2) { 93 | return -1; 94 | } 95 | return 1; 96 | }; 97 | 98 | AVLTree.prototype.add = function(n) { 99 | var o = this.compare(n, this.value); 100 | if (o == 0) { 101 | return false; 102 | } 103 | 104 | var ret = false; 105 | if (o == -1) { 106 | if (this.left == null) { 107 | this.left = new AVLTree(n); 108 | ret = true; 109 | } else { 110 | ret = this.left.add(n); 111 | if (ret) { 112 | this.balance(); 113 | } 114 | } 115 | } else if (o == 1) { 116 | if (this.right == null) { 117 | this.right = new AVLTree(n); 118 | ret = true; 119 | } else { 120 | ret = this.right.add(n); 121 | if (ret) { 122 | this.balance(); 123 | } 124 | } 125 | } 126 | 127 | if (ret) { 128 | this.getDepthFromChildren(); 129 | } 130 | return ret; 131 | }; 132 | 133 | // Given the beginning of a value, return the elements if there's a match 134 | AVLTree.prototype.find = function(value) { 135 | 136 | if (value < this.value) { 137 | if (this.left != null) { 138 | return this.left.find(value); 139 | } 140 | } else if (value > this.value) { 141 | if (this.right != null) { 142 | return this.right.find(value); 143 | } 144 | } 145 | return this; 146 | } 147 | 148 | AVLTree.prototype.remove = function(value) { 149 | return deleteRecursively(this, value); 150 | 151 | function deleteRecursively(root, value) { 152 | if (!root) { 153 | return null; 154 | } else if (value < root.value) { 155 | root.left = deleteRecursively(root.left, value); 156 | } else if (value > root.value) { 157 | root.right = deleteRecursively(root.right, value); 158 | } else { 159 | //no child 160 | if (!root.left && !root.right) { 161 | return null; // case 1 162 | } else if (!root.left) { 163 | root = root.right; 164 | return root; 165 | } else if (!root.right) { 166 | root = root.left; 167 | return root; 168 | } else { 169 | var temp = findMin(root.right); 170 | root.value = temp.value; 171 | root.right = deleteRecursively(root.right, temp.value); 172 | return root; 173 | } 174 | } 175 | root.updateInNewLocation(); 176 | return root; 177 | } 178 | 179 | function findMin(root) { 180 | while (root.left) { 181 | root = root.left; 182 | } 183 | return root; 184 | } 185 | } 186 | 187 | var avlTest = new AVLTree(1, ''); 188 | avlTest.add(2); 189 | avlTest.add(3); 190 | avlTest.add(4); 191 | avlTest.add(5); 192 | avlTest.add(123); 193 | avlTest.add(203); 194 | avlTest.add(2222); 195 | 196 | console.log(avlTest); -------------------------------------------------------------------------------- /Data Structures/AdjacencyMatrix.js: -------------------------------------------------------------------------------- 1 | 2 | function AdjacencyMatrix (vertexSize) { 3 | this.matrix = new Array(vertexSize); 4 | // create matrix 5 | for (var i=0; ivalue){ 19 | // let's increment if it's not a null and insert if it is a null 20 | if(currentRoot.left!=null){ 21 | currentRoot = currentRoot.left; 22 | }else{ 23 | currentRoot.left = thisNode; 24 | break; 25 | } 26 | } else if (currentRoot.value root.value ) { 56 | root.right = deleteRecursively(root.right, value); 57 | } else { 58 | //no child 59 | if(!root.left && !root.right){ 60 | return null; // case 1 61 | }else if(!root.left){ 62 | root = root.right; 63 | return root; 64 | }else if(!root.right){ 65 | root = root.left; 66 | return root; 67 | }else { 68 | var temp = findMin(root.right); 69 | root.value = temp.value; 70 | root.right = deleteRecursively(root.right, temp.value); 71 | return root; 72 | } 73 | } 74 | return root; 75 | } 76 | 77 | function findMin(root){ 78 | while(root.left){ 79 | root = root.left; 80 | } 81 | return root; 82 | } 83 | } 84 | 85 | // Access 86 | // Search 87 | // Time Complexity: O(h) 88 | // Space Complexity: O(h) 89 | BinarySearchTree.prototype.accessNode = function(value){ 90 | var currentRoot = this._root, 91 | found = false; 92 | while(currentRoot){ 93 | if(currentRoot.value > value){ 94 | currentRoot = currentRoot.left; 95 | }else if(currentRoot.value < value){ 96 | currentRoot = currentRoot.right; 97 | }else{ 98 | return currentRoot; 99 | } 100 | } 101 | return null; 102 | } 103 | 104 | // Search 105 | // Time Complexity: O(h) 106 | // Space Complexity: O(h) 107 | BinarySearchTree.prototype.findNode = function(value){ 108 | var currentRoot = this._root, 109 | found = false; 110 | while(currentRoot){ 111 | if(currentRoot.value > value){ 112 | currentRoot = currentRoot.left; 113 | }else if(currentRoot.value < value){ 114 | currentRoot = currentRoot.right; 115 | }else{ 116 | //we've found the node 117 | found = true; 118 | break; 119 | } 120 | } 121 | return found; 122 | } 123 | 124 | module.exports = BinarySearchTree; -------------------------------------------------------------------------------- /Data Structures/CustomSet.js: -------------------------------------------------------------------------------- 1 | // Custom implementation of the JavaScript set using JavaScript object only 2 | function customSet () { 3 | this.elements = []; 4 | this.size = 0; 5 | this.mapping = {}; 6 | } 7 | 8 | customSet.prototype.add = function(element) { 9 | if (this.mapping[element]) { 10 | 11 | } 12 | 13 | this.size++; 14 | return this; 15 | }; 16 | 17 | 18 | Set.prototype.isSuperset = function(subset) { 19 | for (var elem of subset) { 20 | if (!this.has(elem)) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | } 26 | 27 | Set.prototype.union = function(setB) { 28 | var union = new Set(this); 29 | for (var elem of setB) { 30 | union.add(elem); 31 | } 32 | return union; 33 | } 34 | 35 | Set.prototype.intersection = function(setB) { 36 | var intersection = new Set(); 37 | for (var elem of setB) { 38 | if (this.has(elem)) { 39 | intersection.add(elem); 40 | } 41 | } 42 | return intersection; 43 | } 44 | 45 | Set.prototype.difference = function(setB) { 46 | var difference = new Set(this); 47 | for (var elem of setB) { 48 | difference.delete(elem); 49 | } 50 | return difference; 51 | } 52 | 53 | //Examples 54 | var setA = new Set([1, 2, 3, 4]), 55 | setB = new Set([2, 3]), 56 | setC = new Set([3, 4, 5, 6]); 57 | 58 | setA.isSuperset(setB); // => true 59 | setA.union(setC); // => Set [1, 2, 3, 4, 5, 6] 60 | setA.intersection(setC); // => Set [3, 4] 61 | setA.difference(setC); // => Set [1, 2] -------------------------------------------------------------------------------- /Data Structures/DiGraph.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | Array.prototype.contains = function(name) { 3 | let i = this.length; 4 | while (i--) { 5 | if (this[i].name === name) { 6 | return true; 7 | } 8 | } 9 | return false; 10 | }; 11 | function Node(name) { 12 | this.edges = []; 13 | this.name = name; 14 | }; 15 | 16 | Node.prototype.addEdge = function(end) { 17 | this.edges.push(end); 18 | }; 19 | 20 | // Main 21 | function DirectedGraph() { 22 | this.vertices = []; 23 | }; 24 | 25 | DirectedGraph.prototype.addEdge = function(start, end) { 26 | const first = this.vertices.contains(start); 27 | const second = this.vertices.contains(end); 28 | 29 | if (first) { 30 | //get start node 31 | var i = this.vertices.length; 32 | while (i--) { 33 | if (this.vertices[i].name === start) { 34 | this.vertices[i].addEdge(end); 35 | break; 36 | } 37 | } 38 | } 39 | if (second) { 40 | //get end node 41 | i = this.vertices.length; 42 | while (i--) { 43 | if (this.vertices[i].name === end) { 44 | this.vertices[i].addEdge(start); 45 | break; 46 | } 47 | } 48 | } 49 | 50 | if ((!first) || (!second)) { 51 | if (!first) { 52 | const node = new Node(start); 53 | node.addEdge(end); 54 | this.vertices.push(node); 55 | } 56 | if (!second) { 57 | const node = new Node(end); 58 | node.addEdge(start); 59 | this.vertices.push(node); 60 | } 61 | } 62 | }; 63 | 64 | DirectedGraph.prototype.printNodes = function() { 65 | for (var i = 0; i < this.vertices.length; i++) { 66 | console.log(this.vertices[i].name + ":"); 67 | console.log(this.vertices[i].edges); 68 | } 69 | }; 70 | var digraph1 = new DirectedGraph(); 71 | 72 | digraph1.addEdge("A", "B"); 73 | digraph1.addEdge("B", "C"); 74 | digraph1.addEdge("C", "A"); 75 | digraph1.printNodes(); 76 | // A: B, C 77 | // B: A, C 78 | // C: B, A -------------------------------------------------------------------------------- /Data Structures/DirectedGraph.js: -------------------------------------------------------------------------------- 1 | function Node(name) { 2 | this.edges = []; 3 | this.name = name; 4 | }; 5 | 6 | Node.prototype.addEdge = function(end) { 7 | this.edges.push(end); 8 | }; 9 | 10 | function DirectedGraph() { 11 | this.vertices = []; 12 | }; 13 | 14 | DirectedGraph.prototype.addEdge = function(start, end) { 15 | const first = this.vertices.contains(start); 16 | const second = this.vertices.contains(end); 17 | 18 | if (first) { 19 | //get start node 20 | var i = this.vertices.length; 21 | while (i--) { 22 | if (this.vertices[i].name === start) { 23 | this.vertices[i].addEdge(end); 24 | break; 25 | } 26 | } 27 | } 28 | if (second) { 29 | //get end node 30 | i = this.vertices.length; 31 | while (i--) { 32 | if (this.vertices[i].name === end) { 33 | this.vertices[i].addEdge(start); 34 | break; 35 | } 36 | } 37 | } 38 | 39 | if ((!first) || (!second)) { 40 | if (!first) { 41 | const node = new Node(start); 42 | node.addEdge(end); 43 | this.vertices.push(node); 44 | } 45 | if (!second) { 46 | const node = new Node(end); 47 | node.addEdge(start); 48 | this.vertices.push(node); 49 | } 50 | } 51 | }; -------------------------------------------------------------------------------- /Data Structures/DoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function LinkedListNode(value) { 3 | this.data = value; 4 | this.prev = null; 5 | this.next = null; 6 | } 7 | 8 | function DoublyLinkedList() { 9 | this.head = null; 10 | this.tail = null; 11 | } 12 | 13 | DoublyLinkedList.prototype.addAtFront = function(value) { 14 | if (this.head === null) { //If first node 15 | this.head = new Node(value); 16 | this.tail = this.head; 17 | } else { 18 | var temp = new Node(value); 19 | temp.next = this.head; 20 | this.head.prev = temp; 21 | this.head = temp; 22 | } 23 | }; 24 | 25 | DoublyLinkedList.prototype.addAtEnd = function(value) { 26 | if (this.tail === null) { //If first node 27 | this.tail = new Node(value); 28 | this.head = this.tail; 29 | } else { 30 | var temp = new Node(value); 31 | temp.prev = this.tail; 32 | this.tail.next = temp; 33 | this.tail = temp; 34 | } 35 | }; 36 | 37 | DoublyLinkedList.prototype.removeAtHead = function() { 38 | var toReturn = null; 39 | 40 | if (this.head !== null) { 41 | toReturn = this.head.data; 42 | 43 | if (this.tail === this.head) { 44 | this.head = null; 45 | this.tail = null; 46 | } else { 47 | this.head = this.head.next; 48 | this.head.prev = null; 49 | } 50 | } 51 | return toReturn; 52 | }; 53 | 54 | DoublyLinkedList.prototype.removeAtTail = function() { 55 | var toReturn = null; 56 | 57 | if (this.tail !== null) { 58 | toReturn = this.tail.data; 59 | 60 | if (this.tail === this.head) { 61 | this.head = null; 62 | this.tail = null; 63 | } else { 64 | this.tail = this.tail.prev; 65 | this.tail.next = null; 66 | } 67 | } 68 | return toReturn; 69 | }; 70 | 71 | DoublyLinkedList.prototype.each = function(func) { 72 | var curr = this.head; 73 | while (curr !== null) { 74 | func(curr); 75 | curr = curr.next; 76 | } 77 | }; 78 | 79 | DoublyLinkedList.prototype.printList = function() { 80 | this.each((item) => { 81 | console.log(item.data); 82 | }); 83 | }; 84 | 85 | var testList = new DoublyLinkedList(); 86 | 87 | testList.addAtFront({ 88 | 'test': 1 89 | }); 90 | testList.addAtEnd({ 91 | 'test': 2 92 | }); 93 | testList.addAtEnd({ 94 | 'test': 3 95 | }); 96 | testList.addAtEnd({ 97 | 'test': 4 98 | }); 99 | 100 | testList.printList(); // {'test': 1}, {'test': 2}, {'test': 3}, {'test': 4g} 101 | 102 | testList.removeAtHead(); 103 | testList.removeAtHead(); 104 | testList.removeAtTail(); 105 | 106 | testList.printList(); // {'test': 3} -------------------------------------------------------------------------------- /Data Structures/Graph.js: -------------------------------------------------------------------------------- 1 | // Helper 2 | function _extractMin(Q, dist) { 3 | var minimumDistance = Infinity; 4 | var nodeWithMinimumDistance; 5 | 6 | for (var node in Q) { 7 | if (dist[node] <= minimumDistance) { 8 | minimumDistance = dist[node]; 9 | nodeWithMinimumDistance = node; 10 | } 11 | } 12 | return nodeWithMinimumDistance; 13 | } 14 | 15 | // Main 16 | var Graphs = function() { 17 | this.vertices = {}; 18 | }; 19 | 20 | Graphs.prototype.add = function(name, edges) { 21 | edges = edges || null; 22 | this.vertices[name] = edges; 23 | }; 24 | 25 | Graphs.prototype.length = function(u, v) { 26 | return (this.vertices[u][v]); 27 | }; 28 | 29 | // Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in a graph 30 | 31 | Graphs.prototype.Dijkstra = function(source) { 32 | // create vertex set Q 33 | var Q = {}, 34 | dist = {}, 35 | prev = {}; 36 | 37 | for (var vertex in this.vertices) { 38 | // unknown distance set to Infinity 39 | dist[vertex] = Infinity; 40 | prev[vertex] = undefined; 41 | // add v to Q 42 | Q[vertex] = this.vertices[vertex]; 43 | } 44 | // Distance from source to source init to 0 45 | dist[source] = 0; 46 | 47 | // while Q is not empty: 48 | while (!_isEmpty(Q)) { 49 | // u ← vertex in Q with min dist[u] 50 | var u = _extractMin(Q, dist); 51 | 52 | // remove u from Q 53 | delete Q[u]; 54 | 55 | // for each neighbor v of u: 56 | // where v is still in Q. 57 | for (var neighbor in this.vertices[u]) { 58 | // alt ← dist[u] + length(u, v) 59 | var alt = dist[u] + G.length(u, neighbor); 60 | 61 | // A shorter path to neighbor has been found 62 | if (alt < dist[neighbor]) { 63 | dist[neighbor] = alt; 64 | prev[neighbor] = u; 65 | } 66 | } 67 | } 68 | return dist; 69 | }; 70 | 71 | // Usage 72 | var G = new Graphs(); 73 | G.add('S', { 74 | V: 1, 75 | W: 4 76 | }); 77 | G.add('W', { 78 | T: 3 79 | }); 80 | G.add('V', { 81 | W: 2, 82 | T: 6 83 | }); 84 | G.add('T'); 85 | console.log(G.Dijkstra('S')); // {"S": 0, "T":6, "V":1, "W": 3} -------------------------------------------------------------------------------- /Data Structures/GraphClass.js: -------------------------------------------------------------------------------- 1 | // Main 2 | // Generalized Graph 3 | function GraphClass() { 4 | this.V = 0; // number of vertices 5 | this.E = 0; // number of edges 6 | this.edges = []; 7 | this.vertices = []; 8 | } 9 | 10 | GraphClass.prototype.addEdge = function(vertex1, vertex2) { 11 | this.E++; // increment the number of edges 12 | 13 | this.edges[vertex1].push(vertex2); 14 | this.edges[vertex2].push(vertex1); 15 | } 16 | 17 | GraphClass.prototype.addVertex = function(vertex) { 18 | this.V++; // increment the number of vertices 19 | 20 | this.vertices.push(vertex); 21 | this.edges[vertex] = []; 22 | } 23 | 24 | GraphClass.prototype.removeEdge = function(vertex1, vertex2) { 25 | var index1 = this.edges[vertex1] ? this.edges[vertex1].indexOf(vertex2) : -1; 26 | var index2 = this.edges[vertex2] ? this.edges[vertex2].indexOf(vertex1) : -1; 27 | if (~index1) { 28 | this.edges[vertex1].splice(index1, 1); 29 | this.E--; // decrement the number of edges 30 | this.cleanUpEdgesArray(vertex1); 31 | } 32 | if (~index2) { 33 | this.edges[vertex2].splice(index2, 1); 34 | this.cleanUpEdgesArray(vertex2); 35 | } 36 | }; 37 | 38 | GraphClass.prototype.removeVertex = function(vertex) { 39 | var index = this.vertices.indexOf(vertex); 40 | if (~index) { 41 | this.vertices.splice(index, 1); 42 | } 43 | while (this.edges[vertex].length) { 44 | var adjacentVertex = this.edges[vertex].pop(); 45 | this.removeEdge(adjacentVertex, vertex); 46 | } 47 | this.V--; // decrement the number of vertices 48 | }; 49 | 50 | GraphClass.prototype.cleanUpEdgesArray = function(vertex) { 51 | if (this.edges[vertex].length == 0) { 52 | delete this.edges[vertex]; 53 | } 54 | } 55 | 56 | GraphClass.prototype.traverseBFS = function(vertex, fn) { 57 | 58 | if (!~this.vertices.indexOf(vertex)) { 59 | return false; // vertex is not found 60 | } 61 | 62 | var queue = []; 63 | queue.push(vertex); 64 | var visited = []; 65 | visited[vertex] = true; 66 | 67 | while (queue.length) { 68 | vertex = queue.shift(); 69 | fn(vertex); 70 | for (var i = 0; i < this.edges[vertex].length; i++) { 71 | if (!visited[this.edges[vertex][i]]) { 72 | visited[this.edges[vertex][i]] = true; 73 | queue.push(this.edges[vertex][i]); 74 | } 75 | } 76 | } 77 | }; 78 | 79 | GraphClass.prototype.traverseDFS = function(vertex, fn) { 80 | if (!~this.vertices.indexOf(vertex)) { 81 | return console.log('Vertex not found'); 82 | } 83 | var visited = []; 84 | this._traverseDFS(vertex, visited, fn); 85 | }; 86 | 87 | GraphClass.prototype._traverseDFS = function(vertex, visited, fn) { 88 | visited[vertex] = true; 89 | if (this.edges[vertex] !== undefined) { 90 | fn(vertex); 91 | } 92 | for (var i = 0; i < this.edges[vertex].length; i++) { 93 | if (!visited[this.edges[vertex][i]]) { 94 | this._traverseDFS(this.edges[vertex][i], visited, fn); 95 | } 96 | } 97 | }; 98 | 99 | var graph1 = new GraphClass(); 100 | graph1.addVertex(1); 101 | graph1.addVertex(2); 102 | graph1.addEdge(1, 2); 103 | graph1.addVertex(3); 104 | graph1.addVertex(4); 105 | graph1.addVertex(5); 106 | graph1.addEdge(3, 4); 107 | graph1.addEdge(4, 5); 108 | graph1.addEdge(1, 5); 109 | graph1.addEdge(2, 3); 110 | graph1.traverseDFS(1, (vertex) => { 111 | console.log(vertex); 112 | }); // 1 2 3 4 5 -------------------------------------------------------------------------------- /Data Structures/LRU.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function DLLNode(key, data) { 3 | this.key = key; 4 | this.data = data; 5 | this.next = null; 6 | this.prev = null; 7 | } 8 | 9 | function LRUCache(capacity) { 10 | this.keys = {}; 11 | this.capacity = capacity; 12 | this.size = 0; 13 | this.head = null; 14 | } 15 | 16 | LRUCache.prototype.set = function(key, value) { 17 | let node = new DLLNode(key, value); 18 | this.keys[key] = node; 19 | if (this.size == 0) { 20 | this.head = node; 21 | } else { 22 | this.insertHead(node); 23 | } 24 | this.size++; 25 | }; 26 | 27 | LRUCache.prototype.insertHead = function(node) { 28 | let temp = this.head; 29 | this.head = node; 30 | node.next = temp; 31 | temp.prev = node; 32 | }; 33 | 34 | LRUCache.prototype.get = function(key) { 35 | let node = this.keys[key]; 36 | if (node.prev && node.next) { 37 | node.prev.next = node.next; 38 | node.next.prev = node.prev; 39 | node.prev = null; 40 | node.next = null; 41 | this.insertHead(node); 42 | } else if (!node.next) { 43 | let temp = node.prev; 44 | temp.next = null; 45 | node.prev = null; 46 | this.insertHead(node); 47 | } 48 | return node.data; 49 | } 50 | 51 | LRUCache.prototype.evict = function() { 52 | let node = this.head, 53 | temp; 54 | 55 | while (node.next.next) { 56 | node = node.next; 57 | } 58 | temp = node.next; 59 | delete this.keys[temp.key]; 60 | node.next = null 61 | this.size--; 62 | }; 63 | 64 | LRUCache.prototype.print = function() { 65 | let node = this.head; 66 | while (node) { 67 | console.log(node.data) 68 | node = node.next; 69 | } 70 | }; 71 | var myLRU = new LRUCache(5); 72 | 73 | myLRU.set(1, 1); 74 | myLRU.set(2, 2); 75 | myLRU.set(3, 3); 76 | myLRU.print(); // 1, 2, 3 77 | myLRU.evict(); // pops the oldest element in cache out: 1 78 | myLRU.print(); // 2, 3 -------------------------------------------------------------------------------- /Data Structures/LinkedList.js: -------------------------------------------------------------------------------- 1 | // Constructor 2 | function LinkedListNode(data) { 3 | this.data = data; 4 | this.next = null; 5 | } 6 | 7 | // Constructor 8 | function SingleLinkedList(){ 9 | this.head = null; 10 | this.size = 0; 11 | } 12 | 13 | // Helpers 14 | SingleLinkedList.prototype.isEmpty = function(){ 15 | return this.size == 0; 16 | } 17 | 18 | 19 | // Insertion 20 | // Time Complexity: O(n) 21 | // Space Complexity: O(1) 22 | SingleLinkedList.prototype.push = function(value) { 23 | var node = new LinkedListNode(value), 24 | currentNode = this.head; 25 | 26 | // if empty, and first element to be added 27 | if (!currentNode) { 28 | this.head = node; 29 | this.size++; 30 | return node; 31 | } 32 | 33 | // get to the end 34 | while (currentNode.next) { 35 | currentNode = currentNode.next; 36 | } 37 | currentNode.next = node; 38 | 39 | this.size++; 40 | 41 | return node; 42 | }; 43 | 44 | // Deletion 45 | // Time Complexity: O(n) 46 | // Space Complexity: O(1) 47 | SinglyLinkedList.prototype.remove = function(value) { 48 | var currentHead = this.head; 49 | if(currentHead.data==value){ 50 | // just shift the head over. Head is now this new value 51 | this.head = currentHead.next; 52 | }else{ 53 | var prev = currentHead; 54 | while(currentHead.next){ 55 | if(currentHead.data==value){ 56 | // remove by skipping 57 | prev.next = currentHead.next; 58 | prev = currentHead; 59 | currentHead = currentHead.next; 60 | break; // break out of the loop 61 | } 62 | prev = currentHead; 63 | currentHead = currentHead.next; 64 | } 65 | //if wasn't found in the middle or head, must be tail 66 | if(currentHead.data==value){ 67 | prev.next = null; 68 | } 69 | } 70 | this.size--; 71 | }; 72 | 73 | // Access: 74 | // Time Complexity: O(n) 75 | // Space Complexity: O(n) 76 | SinglyLinkedList.prototype.access = function(N) { 77 | var currentHead = this.head; 78 | var counter=0; 79 | while(currentHead.next){ 80 | if(N == counter){ 81 | return currentHead; 82 | } 83 | counter++; 84 | currentHead = currentHead.next; 85 | } 86 | }; 87 | 88 | // Search: 89 | // Time Complexity: O(n) 90 | // Space Complexity: O(n) 91 | SinglyLinkedList.prototype.find = function(value) { 92 | var currentHead = this.head; 93 | while(currentHead.next){ 94 | if(currentHead.data == value){ 95 | return true; 96 | } 97 | currentHead = currentHead.next; 98 | } 99 | return false; 100 | }; 101 | 102 | module.exports = SingleLinkedList; -------------------------------------------------------------------------------- /Data Structures/MaxHeap.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function MaxHeap() { 3 | this.items = []; 4 | }; 5 | 6 | MaxHeap.prototype.swap = function(index1, index2) { 7 | var temp = this.items[index1]; 8 | this.items[index1] = this.items[index2]; 9 | this.items[index2] = temp; 10 | }; 11 | 12 | MaxHeap.prototype.parentIndex = function(index) { 13 | return Math.floor((index - 1) / 2); 14 | }; 15 | 16 | MaxHeap.prototype.leftChildIndex = function(index) { 17 | return index * 2 + 1; 18 | }; 19 | 20 | MaxHeap.prototype.rightChildrenIndex = function(index) { 21 | return index * 2 + 2; 22 | }; 23 | 24 | MaxHeap.prototype.parent = function(index) { 25 | return this.items[this.parentIndex(index)]; 26 | }; 27 | 28 | MaxHeap.prototype.leftChild = function(index) { 29 | return this.items[this.leftChildIndex(index)]; 30 | }; 31 | 32 | MaxHeap.prototype.rightChild = function(index) { 33 | return this.items[this.rightChildrenIndex(index)]; 34 | }; 35 | 36 | MaxHeap.prototype.add = function(item) { 37 | this.items[this.items.length] = item; 38 | this.bubbleUp(); 39 | }; 40 | 41 | MaxHeap.prototype.peak = function() { 42 | return this.items[0]; 43 | }; 44 | 45 | MaxHeap.prototype.poll = function() { 46 | var item = this.items[0]; 47 | this.items[0] = this.items[this.items.length-1]; 48 | this.items.pop(); 49 | this.bubbleDown(); 50 | return item; 51 | }; 52 | 53 | MaxHeap.prototype.bubbleDown = function() { 54 | var index = 0; 55 | 56 | while (this.leftChild(index) && this.leftChild(index) > this.items[index]) { 57 | var biggerIndex = this.leftChildIndex(index); 58 | if (this.rightChild(index) && this.rightChild(index) > this.items[biggerIndex]) { 59 | biggerIndex = this.rightChildrenIndex(index); 60 | } 61 | 62 | this.swap(biggerIndex, index); 63 | index = biggerIndex; 64 | } 65 | 66 | }; 67 | 68 | MaxHeap.prototype.bubbleUp = function() { 69 | var index = this.items.length - 1; 70 | 71 | while (this.parent(index) && this.parent(index) < this.items[index]) { 72 | this.swap(this.parentIndex(index), index); 73 | index = this.parentIndex(index); 74 | } 75 | 76 | }; -------------------------------------------------------------------------------- /Data Structures/MinHeap.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function MinHeap() { 3 | this.items = []; 4 | }; 5 | 6 | MinHeap.prototype.swap = function(index1, index2) { 7 | var temp = this.items[index1]; 8 | this.items[index1] = this.items[index2]; 9 | this.items[index2] = temp; 10 | }; 11 | 12 | MinHeap.prototype.parentIndex = function(index) { 13 | return Math.floor((index - 1) / 2); 14 | }; 15 | 16 | MinHeap.prototype.leftChildIndex = function(index) { 17 | return index * 2 + 1; 18 | }; 19 | 20 | MinHeap.prototype.rightChildrenIndex = function(index) { 21 | return index * 2 + 2; 22 | }; 23 | 24 | MinHeap.prototype.parent = function(index) { 25 | return this.items[this.parentIndex(index)]; 26 | }; 27 | 28 | MinHeap.prototype.leftChild = function(index) { 29 | return this.items[this.leftChildIndex(index)]; 30 | }; 31 | 32 | MinHeap.prototype.rightChild = function(index) { 33 | return this.items[this.rightChildrenIndex(index)]; 34 | }; 35 | 36 | MinHeap.prototype.add = function(item) { 37 | this.items[this.items.length] = item; 38 | this.bubbleUp(); 39 | }; 40 | 41 | MinHeap.prototype.peak = function() { 42 | return this.items[0]; 43 | }; 44 | 45 | MinHeap.prototype.poll = function() { 46 | var item = this.items[0]; 47 | this.items[0] = this.items[this.items.length-1]; 48 | this.items.pop(); 49 | this.bubbleDown(); 50 | return item; 51 | }; 52 | 53 | MinHeap.prototype.bubbleDown = function() { 54 | var index = 0; 55 | 56 | while (this.leftChild(index) && this.leftChild(index) < this.items[index]) { 57 | var smallerIndex = this.leftChildIndex(index); 58 | if (this.rightChild(index) && this.rightChild(index) < this.items[smallerIndex]) { 59 | smallerIndex = this.rightChildrenIndex(index); 60 | } 61 | 62 | this.swap(smallerIndex, index); 63 | index = smallerIndex; 64 | } 65 | 66 | }; 67 | 68 | MinHeap.prototype.bubbleUp = function() { 69 | var index = this.items.length - 1; 70 | 71 | while (this.parent(index) && this.parent(index) > this.items[index]) { 72 | this.swap(this.parentIndex(index), index); 73 | index = this.parentIndex(index); 74 | } 75 | 76 | }; -------------------------------------------------------------------------------- /Data Structures/Queue.js: -------------------------------------------------------------------------------- 1 | // Constructor 2 | function Queue(array){ 3 | this.array = []; 4 | if(array) this.array = array; 5 | } 6 | 7 | // Helpers 8 | Queue.prototype.getBuffer = function(){ 9 | return this.array.slice(); 10 | } 11 | 12 | Queue.prototype.isEmpty = function(){ 13 | return this.array.length == 0; 14 | } 15 | 16 | Queue.prototype.peek = function(){ 17 | return this.array[0]; 18 | } 19 | 20 | // Insertion: 21 | // Time Complexity: O(1) 22 | // Space Complexity: O(1) 23 | Queue.prototype.enqueue = function(value){ 24 | return this.array.push(value); 25 | } 26 | 27 | // Deletion: 28 | // Time Complexity: O(1) 29 | // Space Complexity: O(1) 30 | Queue.prototype.dequeue = function() { 31 | return this.array.shift(); 32 | }; 33 | 34 | // Access: 35 | // Time Complexity: O(n) 36 | // Space Complexity: O(n) 37 | Queue.prototype.access = function(n) { 38 | var bufferArray = this.getBuffer(); 39 | if(n<=0) throw 'error' 40 | 41 | var bufferStack = new Queue(bufferArray); 42 | 43 | while(--n!==0){ 44 | bufferStack.dequeue(); 45 | } 46 | return bufferStack.dequeue(); 47 | } 48 | 49 | // Search: 50 | // Time Complexity: O(n) 51 | // Space Complexity: O(n) 52 | Queue.prototype.search = function(element) { 53 | var bufferArray = this.getBuffer(); 54 | var bufferQueue = new Queue(bufferArray); 55 | 56 | while(!bufferQueue.isEmpty()){ 57 | if(bufferQueue.dequeue()==element){ 58 | return true; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | 65 | // Testing code 66 | 67 | // var queue1 = new Queue(); 68 | // queue1.enqueue(1); 69 | // queue1.enqueue(2); 70 | // queue1.enqueue(3); 71 | // console.log(queue1); // {array: [1,2,3]} 72 | // queue1.dequeue(); 73 | // console.log(queue1); // {array: [2,3]} 74 | // queue1.dequeue(); 75 | // console.log(queue1); // {array: [3]} 76 | 77 | module.exports = Queue; -------------------------------------------------------------------------------- /Data Structures/Set.js: -------------------------------------------------------------------------------- 1 | // Example taken directly from MDN 2 | Set.prototype.isSuperset = function(subset) { 3 | for (var elem of subset) { 4 | if (!this.has(elem)) { 5 | return false; 6 | } 7 | } 8 | return true; 9 | } 10 | 11 | Set.prototype.union = function(setB) { 12 | var union = new Set(this); 13 | for (var elem of setB) { 14 | union.add(elem); 15 | } 16 | return union; 17 | } 18 | 19 | Set.prototype.intersection = function(setB) { 20 | var intersection = new Set(); 21 | for (var elem of setB) { 22 | if (this.has(elem)) { 23 | intersection.add(elem); 24 | } 25 | } 26 | return intersection; 27 | } 28 | 29 | Set.prototype.difference = function(setB) { 30 | var difference = new Set(this); 31 | for (var elem of setB) { 32 | difference.delete(elem); 33 | } 34 | return difference; 35 | } 36 | 37 | //Examples 38 | var setA = new Set([1, 2, 3, 4]), 39 | setB = new Set([2, 3]), 40 | setC = new Set([3, 4, 5, 6]); 41 | 42 | setA.isSuperset(setB); // => true 43 | setA.union(setC); // => Set [1, 2, 3, 4, 5, 6] 44 | setA.intersection(setC); // => Set [3, 4] 45 | setA.difference(setC); // => Set [1, 2] -------------------------------------------------------------------------------- /Data Structures/Stack.js: -------------------------------------------------------------------------------- 1 | // Constructor 2 | function Stack(array){ 3 | this.array = []; 4 | if(array) this.array = array; 5 | } 6 | 7 | // Helpers 8 | Stack.prototype.getBuffer = function(){ 9 | return this.array.slice(); 10 | } 11 | 12 | Stack.prototype.isEmpty = function(){ 13 | return this.array.length == 0; 14 | } 15 | 16 | Stack.prototype.peek = function(){ 17 | return this.array[this.array.length-1]; 18 | } 19 | 20 | // Insertion: 21 | // Time Complexity: O(1) 22 | // Space Complexity: O(1) 23 | Stack.prototype.push = function(value){ 24 | this.array.push(value); 25 | } 26 | 27 | // Deletion: 28 | // Time Complexity: O(1) 29 | // Space Complexity: O(1) 30 | Stack.prototype.pop = function() { 31 | return this.array.pop(); 32 | }; 33 | 34 | // Access: 35 | // Time Complexity: O(n) 36 | // Space Complexity: O(n) 37 | Stack.prototype.access = function(n) { 38 | var bufferArray = this.getBuffer(); 39 | if(n<=0) throw 'error' 40 | 41 | var bufferStack = new Stack(bufferArray); 42 | 43 | while(--n!==0){ 44 | bufferStack.pop(); 45 | } 46 | return bufferStack.pop(); 47 | }; 48 | 49 | // Search: 50 | // Time Complexity: O(n) 51 | // Space Complexity: O(n) 52 | Stack.prototype.search = function(element) { 53 | var bufferArray = this.getBuffer(); 54 | var bufferStack = new Stack(bufferArray); 55 | 56 | while(!bufferStack.isEmpty()){ 57 | if(bufferStack.pop()==element){ 58 | return true; 59 | } 60 | } 61 | 62 | return false; 63 | }; 64 | 65 | 66 | // Testing code 67 | 68 | // var stack1 = new Stack(); 69 | 70 | // stack1.push(1); 71 | // stack1.push(2); 72 | // stack1.push(3); 73 | 74 | // console.log(stack1); // {array: [1,2,3]} 75 | 76 | // stack1.pop(1); 77 | // stack1.pop(2); 78 | // stack1.pop(3); 79 | 80 | // console.log(stack1); // {array: []} 81 | 82 | module.exports = Stack; -------------------------------------------------------------------------------- /Data Structures/Tree.js: -------------------------------------------------------------------------------- 1 | // Constructor for TreeNode 2 | function TreeNode(data){ 3 | this.data = data; 4 | this.children = []; 5 | } 6 | 7 | // Constructor for BinaryTreeNode 8 | function BinaryTreeNode(data){ 9 | this.data = data; 10 | this.left = null; 11 | this.right= null; 12 | } 13 | 14 | // Constructor for BinaryTree 15 | function BinaryTree(){ 16 | this._root = null; 17 | } 18 | 19 | // Traversal techniques 20 | 21 | // h: height of the binary tree. Ideally n log_2(n) 22 | 23 | // Pre-Order Traversal: 24 | // Time Complexity: O(n) 25 | // Space Complexity: O(h) 26 | BinaryTree.prototype.traversePreOrder = function(){ 27 | traversePreOrderHelper(this._root); 28 | function traversePreOrderHelper(node){ 29 | if(!node) 30 | return; 31 | console.log(node); 32 | traversePreOrderHelper(node.left); 33 | traversePreOrderHelper(node.right); 34 | } 35 | } 36 | 37 | // In-Order Traversal: 38 | // Time Complexity: O(n) 39 | // Space Complexity: O(h) 40 | BinaryTree.prototype.traverseInOrder = function(){ 41 | traverseInOrderHelper(this._root); 42 | function traverseInOrderHelper(node){ 43 | if(!node) 44 | return; 45 | traverseInOrderHelper(node.left); 46 | console.log(node); 47 | traverseInOrderHelper(node.right); 48 | } 49 | } 50 | 51 | // Post-Order Traversal: 52 | // Time Complexity: O(n) 53 | // Space Complexity: O(h) 54 | BinaryTree.prototype.traversePostOrder = function(){ 55 | traversePostOrderHelper(this._root); 56 | function traversePostOrderHelper(node){ 57 | if(node.left){ 58 | traversePostOrderHelper(node.left); 59 | } 60 | if(node.right){ 61 | traversePostOrderHelper(node.right); 62 | } 63 | console.log(node); 64 | } 65 | } 66 | 67 | module.exports = BinaryTree; -------------------------------------------------------------------------------- /Data Structures/Trie.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function TrieNode() { 3 | this.children = {}; // table 4 | this.endOfWord = false; 5 | } 6 | 7 | function Trie() { 8 | this.root = new TrieNode(); 9 | } 10 | 11 | Trie.prototype.insert = function(word) { 12 | var current = this.root; 13 | for (var i = 0; i < word.length; i++) { 14 | var ch = word.charAt(i); 15 | var node = current.children[ch]; 16 | if (node == null) { 17 | node = new TrieNode(); 18 | current.children[ch] = node; 19 | } 20 | current = node; 21 | } 22 | //mark the current nodes endOfWord as true 23 | current.endOfWord = true; 24 | } 25 | 26 | Trie.prototype.search = function(word) { 27 | var current = this.root; 28 | for (var i = 0; i < word.length; i++) { 29 | var ch = word.charAt(i); 30 | var node = current.children[ch]; 31 | //if node does not exist for given char then return false 32 | if (node == null) { 33 | return false; 34 | } 35 | current = node; 36 | } 37 | //return true of current's endOfWord is true else return false. 38 | return current.endOfWord; 39 | } 40 | 41 | Trie.prototype.delete = function(word) { 42 | this.deleteRecursively(this.root, word, 0); 43 | } 44 | 45 | Trie.prototype.deleteRecursively = function(current, word, index) { 46 | if (index == word.length) { 47 | //when end of word is reached only delete if currrent.endOfWord is true. 48 | if (!current.endOfWord) { 49 | return false; 50 | } 51 | current.endOfWord = false; 52 | //if current has no other mapping then return true 53 | return Object.keys(current.children).length == 0; 54 | } 55 | var ch = word.charAt(index); 56 | var node = current.children[ch]; 57 | if (node == null) { 58 | return false; 59 | } 60 | var shouldDeleteCurrentNode = this.deleteRecursively(node, word, index + 1); 61 | 62 | // if true is returned then 63 | // delete the mapping of character and trienode reference from map. 64 | if (shouldDeleteCurrentNode) { 65 | delete current.children[ch]; 66 | //return true if no mappings are left in the map. 67 | return Object.keys(current.children).length == 0; 68 | } 69 | return false; 70 | } 71 | 72 | var trieclass1 = new Trie(); 73 | trieclass1.insert("sammie"); 74 | trieclass1.insert("simran"); 75 | console.log(trieclass1.search("simran")); // true 76 | trieclass1.delete("sammie"); 77 | trieclass1.delete("sammie"); 78 | trieclass1.search("sammie"); // false 79 | console.log(trieclass1.search("simran")); // false -------------------------------------------------------------------------------- /Data Structures/UndirectedGraph.js: -------------------------------------------------------------------------------- 1 | // Constructor for GraphClass 2 | function GraphClass() { 3 | this.V = 0; // number of vertices 4 | this.E = 0; // number of edges 5 | this.edges = []; 6 | this.vertices = []; 7 | } 8 | 9 | GraphClass.prototype.addEdge = function(vertex1,vertex2) { 10 | this.E++; // increment the number of edges 11 | 12 | this.edges[vertex1].push(vertex2); 13 | this.edges[vertex2].push(vertex1); 14 | } 15 | 16 | GraphClass.prototype.addVertex = function (vertex) { 17 | this.V++; // increment the number of vertices 18 | 19 | this.vertices.push(vertex); 20 | this.edges[vertex] = []; 21 | } 22 | 23 | GraphClass.prototype.removeEdge = function(vertex1, vertex2) { 24 | var index1 = this.edges[vertex1] ? this.edges[vertex1].indexOf(vertex2) : -1; 25 | var index2 = this.edges[vertex2] ? this.edges[vertex2].indexOf(vertex1) : -1; 26 | if (~index1) { 27 | this.edges[vertex1].splice(index1, 1); 28 | this.E--; // decrement the number of edges 29 | } 30 | if (~index2) { 31 | this.edges[vertex2].splice(index2, 1); 32 | } 33 | }; 34 | 35 | GraphClass.prototype.removeVertex = function(vertex) { 36 | var index = this.vertices.indexOf(vertex); 37 | if (~index) { 38 | this.vertices.splice(index, 1); 39 | } 40 | while (this.edges[vertex].length) { 41 | var adjacentVertex = this.edges[vertex].pop(); 42 | this.removeEdge(adjacentVertex, vertex); 43 | } 44 | this.V--; // decrement the number of vertices 45 | }; 46 | 47 | module.exports = GraphClass; -------------------------------------------------------------------------------- /Design Patterns/Decorator.js: -------------------------------------------------------------------------------- 1 | // Animal constructor 2 | function Animal(animalType) { 3 | this.animalType = animalType; 4 | this.color = "black"; 5 | } 6 | 7 | // Test instance for a basic Animal 8 | var testInstance = new Animal("Dog"); 9 | console.log(testInstance); // { animalType: "dog", color: 'black'} 10 | 11 | // Lets create a new instance of Animal to be decorated as Cat 12 | var cat = new Animal("Cat"); 13 | cat.setColor = function(color) { 14 | this.color = color; 15 | } 16 | 17 | // Test the value setters and value assignment works correctly 18 | cat.setColor("blue"); 19 | console.log(cat); // prints { animalType: "dog", color: "blue" } -------------------------------------------------------------------------------- /Design Patterns/Facade.js: -------------------------------------------------------------------------------- 1 | var subSystem1 = function() { 2 | this.operation1 = function() { 3 | console.log("executing operation 1"); 4 | } 5 | } 6 | var subSystem2 = function() { 7 | this.operation2 = function() { 8 | console.log("executing operation 2"); 9 | } 10 | } 11 | var subSystem3 = function() { 12 | this.operation3 = function() { 13 | console.log("executing operation 3"); 14 | } 15 | } 16 | var FacadeSystem = function() { 17 | this.subSystem1 = new subSystem1(); 18 | this.subSystem2 = new subSystem2(); 19 | this.subSystem3 = new subSystem3(); 20 | 21 | // Start the subsystems in the constructor to run when created 22 | this.subSystem1.operation1(); 23 | this.subSystem2.operation2(); 24 | this.subSystem3.operation3(); 25 | } 26 | var facadeSystem = new FacadeSystem(); 27 | // prints: "executing operation 1", "executing operation 2", "executing operation 3" -------------------------------------------------------------------------------- /Design Patterns/Factory.js: -------------------------------------------------------------------------------- 1 | function Joe(){ 2 | this.name = "Joe"; 3 | } 4 | 5 | function Chris(){ 6 | this.name = "Chris"; 7 | } 8 | 9 | function Cole(){ 10 | this.name = "Cole"; 11 | } 12 | 13 | function inheritsFrom (child, parent) { 14 | child.prototype = Object.create(parent.prototype); 15 | }; 16 | 17 | function RoomFactory () { 18 | this.createRoommate = function (type) { 19 | switch (type) { 20 | case "Joe": 21 | return new Joe(); 22 | break; 23 | case "Chris": 24 | return new Chris(); 25 | break; 26 | case "Cole": 27 | return new Cole(); 28 | break; 29 | default: 30 | return null; 31 | break; 32 | } 33 | } 34 | } 35 | var room301 = new RoomFactory(); 36 | console.log(room301.createRoommate("Joe")); // {name: "Joe"} 37 | console.log(room301.createRoommate("Chris")); // {name: "Chris"} 38 | console.log(room301.createRoommate("Cole")); // {name: "Cole"} -------------------------------------------------------------------------------- /Design Patterns/Observer.js: -------------------------------------------------------------------------------- 1 | function observable() { 2 | this.observers = []; // list of observer objects 3 | } 4 | 5 | observable.prototype.attach = function(observer) { 6 | this.observers.push(observer); 7 | } 8 | 9 | observable.prototype.detach = function(observer) { 10 | for (var i in this.observers) { 11 | if (this.observers[i] == observer) { 12 | this.observers.splice(i, 1); 13 | break; 14 | } 15 | } 16 | } 17 | 18 | observable.prototype.notify = function() { 19 | for (i in this.observers) { 20 | this.observers[i].update(); 21 | } 22 | } 23 | 24 | function observer(name) { 25 | this.name = name; 26 | this.update = function() { 27 | console.log(this.name + " got updated"); 28 | } 29 | } 30 | 31 | var obs = new observable(); 32 | var ob1 = new observer("name"); 33 | var ob2 = new observer("name2"); 34 | 35 | obs.attach(ob1); 36 | obs.attach(ob2); 37 | // obs = {observers: [{name: 'name', update:...}, {name: 'name2', update: ...}]} 38 | 39 | obs.notify(); 40 | // prints 'name got updated'. 'name2 got updated' 41 | obs.detach(ob2); 42 | //obs = {observers: [{name: 'name', update:...}, {name: 'name2', update: ...}]} 43 | obs.notify(); 44 | // prints 'name got updated' -------------------------------------------------------------------------------- /Design Patterns/RevealingModule.js: -------------------------------------------------------------------------------- 1 | var personModule = (function() { 2 | var privateVar = "", 3 | publicVar = ""; 4 | 5 | function publicGetName() { 6 | return "Name:" + privateVar; 7 | } 8 | 9 | function publicSetName(strName) { 10 | privateVar = strName; 11 | } 12 | 13 | // Reveal public pointers to 14 | // private functions and properties 15 | return { 16 | setName: publicSetName, 17 | getName: publicGetName 18 | }; 19 | })(); 20 | // before any name is set 21 | console.log(personModule.getName()); // returns 'Name: '; 22 | personModule.setName("Sammie Bae"); 23 | console.log(personModule.getName()); // 'Name: Sammie Bae'; -------------------------------------------------------------------------------- /Design Patterns/Singleton.js: -------------------------------------------------------------------------------- 1 | function SingletonObject() { 2 | this.name = "Sample Singlteon"; 3 | } 4 | 5 | function SingletonLayer() { 6 | this._instance = null; 7 | } 8 | 9 | SingletonLayer.prototype.getInstance = function() { 10 | if (!this._instance) 11 | this._instance = new SingletonObject(); 12 | return this._instance; 13 | } 14 | 15 | var layer = new SingletonLayer(), 16 | instance1 = layer.getInstance(); 17 | 18 | console.log(instance1); // {name: "Sample Singlteon"} 19 | // change the instance 20 | instance1['prop_add'] = true; 21 | console.log(instance1); // {name: "Sample Singlteon", prop_add: true} 22 | 23 | var instance2 = layer.getInstance(); 24 | console.log(instance2); // {name: "Sample Singlteon", prop_add: true} -------------------------------------------------------------------------------- /Examples/LocalStorage.js: -------------------------------------------------------------------------------- 1 | // before refreshing the page 2 | localStorage.setItem("testKey","testValue"); 3 | 4 | // Refresh the page -> 5 | localStorage.getItem("testKey"); // prints "testValue" 6 | 7 | // data persists after reload -------------------------------------------------------------------------------- /Graphs/TopologicalSort.js: -------------------------------------------------------------------------------- 1 | function Graph (vertices) { 2 | this.graph = {}; 3 | this.vertices = vertices; 4 | } 5 | 6 | Graph.prototype.addEdge = function(u,v) { 7 | if (!this.graph[u]) 8 | this.graph[u] = [v]; 9 | else 10 | this.graph[u].push(v); 11 | }; 12 | 13 | Graph.prototype.topologicalSortUtil = function(v, visited, stack) { 14 | visited[v] = true; 15 | 16 | for (var i in this.graph[v]) { 17 | if (visited[i] == false) { 18 | this.topologicalSortUtil(i, visited, stack) 19 | } 20 | } 21 | stack.unshift(v); 22 | }; 23 | 24 | Graph.prototype.topologicalSort = function() { 25 | var visited = [], 26 | stack = []; 27 | 28 | for (var i=0; i < this.vertices; i++) { 29 | visited.push(false); 30 | } 31 | 32 | for (var i=0; i < this.vertices; i++) { 33 | if (visited[i] == false) { 34 | this.topologicalSortUtil(i, visited, stack) 35 | } 36 | } 37 | return stack; 38 | }; 39 | 40 | var g = new Graph(6); 41 | g.addEdge(5, 2); 42 | g.addEdge(5, 0); 43 | g.addEdge(4, 0); 44 | g.addEdge(4, 1); 45 | g.addEdge(2, 3); 46 | g.addEdge(3, 1); 47 | var topologicalOrder = g.topologicalSort(); 48 | 49 | console.log(topologicalOrder); -------------------------------------------------------------------------------- /Problems/Arrays/BoyerMooreVote.js: -------------------------------------------------------------------------------- 1 | function BoyerMooreVote(arr) { 2 | let count = 0, 3 | candidate = 0; 4 | 5 | for (let i=0; i < arr.length; i++) { 6 | if (count == 0){ 7 | candidate = arr[i]; 8 | count = 1; 9 | } else { 10 | if (arr[i] == candidate) { 11 | count += 1; 12 | } else { 13 | count -= 1; 14 | } 15 | } 16 | } 17 | 18 | if (count == 0) { 19 | return null; 20 | } 21 | count = 0; 22 | for (let i=0; i < arr.length; i++) { 23 | if (candidate == arr[i]) { 24 | count += 1; 25 | } 26 | } 27 | if (count > Math.floor(arr.length/2)) { 28 | return candidate; 29 | } else { 30 | return null; 31 | } 32 | } 33 | 34 | console.log(BoyerMooreVote([1,23,4,1,2,1,1,1,1,1])); // 1 35 | console.log(BoyerMooreVote([1,2,3])); // null -------------------------------------------------------------------------------- /Problems/Arrays/arraySlice.js: -------------------------------------------------------------------------------- 1 | function arraySlice (array, beginIndex, endIndex) { 2 | // If no parameters passed, return the array 3 | if (!beginIndex && !endIndex){ 4 | return array; 5 | } 6 | 7 | // If only beginning index is found, set endIndex to size 8 | endIndex = array.length; 9 | 10 | var partArray = []; 11 | 12 | // If both begin and end index specified return the part of the array 13 | for (var i=beginIndex; i= 0) { 7 | nums[Math.abs(nums[i] - 1)] *= -1; 8 | } else { 9 | duplicates.push(Math.abs(nums[i])); 10 | } 11 | } 12 | return duplicates; 13 | } 14 | console.log(duplicatesInArray([1, 2, 3, 1, 4])); // [1] 15 | console.log(duplicatesInArray([1, 2, 3, 4, 3, 5, 6, 6, 5, 7])); // [3,6,5] -------------------------------------------------------------------------------- /Problems/Arrays/findLargestProductItems.js: -------------------------------------------------------------------------------- 1 | // Main 2 | // Realize that greatest product of two is yielded by the greatest sum of the two 3 | function findLargestProductItems(arr) { 4 | var secondHighest = -Infinity, 5 | highest = -Infinity; 6 | 7 | for (var i = 0, arrLength = arr.length; i < arrLength; i++) { 8 | var current = arr[i]; 9 | 10 | if (current > highest) { 11 | secondHighest = highest; 12 | highest = current; 13 | } else if (current > secondHighest) { 14 | secondHighest = current; 15 | } 16 | } 17 | return [secondHighest, highest]; 18 | } 19 | 20 | console.log(findLargestProductItems([12, 13, 17, 10, 34, 1])); // [34, 17] 21 | console.log(findLargestProductItems([12, 13, 17, 10, 1])); // [13, 17] -------------------------------------------------------------------------------- /Problems/Arrays/findSum.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function findSum(arr, weight) { 3 | for (var i = 0, arrLength = arr.length; i < arrLength; i++) { 4 | for (var j = i + 1; j < arrLength; j++) { 5 | if (arr[i] + arr[j] == weight) { 6 | return [i, j]; 7 | } 8 | } 9 | } 10 | return -1; 11 | } -------------------------------------------------------------------------------- /Problems/Arrays/findSumBetter.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function findSumBetter(arr, weight) { 3 | var hashtable = {}; 4 | 5 | for (var i = 0, arrLength = arr.length; i < arrLength; i++) { 6 | var currentElement = arr[i], 7 | difference = weight - currentElement; 8 | 9 | // check the right one already exists 10 | if (hashtable[difference]) { 11 | return [i, hashtable[weight - currentElement]]; 12 | } else { 13 | // store index 14 | hashtable[difference] = i; 15 | } 16 | } 17 | return -1; 18 | } -------------------------------------------------------------------------------- /Problems/Arrays/majorityElement.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function majorityElement(nums) { 3 | var majority = nums[0], 4 | counter = 1; 5 | 6 | for (var i = 1, numsLength = nums.length; i < numsLength; i++) { 7 | if (counter === 0) { 8 | counter = 1; 9 | majority = nums[i]; 10 | } else if (nums[i] === majority) { 11 | counter++; 12 | } else { 13 | counter--; 14 | } 15 | } 16 | return majority; 17 | } -------------------------------------------------------------------------------- /Problems/Arrays/maxProfit.js: -------------------------------------------------------------------------------- 1 | function maxProfit(prices) { 2 | let minStockPrice = Infinity, 3 | maxAnswer = 0; 4 | 5 | for(let i=0; i 0) { 7 | answerProfit += currentProfit; 8 | } 9 | } 10 | return answerProfit; 11 | }; -------------------------------------------------------------------------------- /Problems/Arrays/maxSubarray.js: -------------------------------------------------------------------------------- 1 | function maxSubArray(nums) { 2 | var maxCurrent = nums[0], 3 | maxGlobal = nums[0]; 4 | 5 | for (var i = 1; i < nums.length; i++) { 6 | maxCurrent = Math.max(nums[i], maxCurrent + nums[i]); 7 | if (maxGlobal < maxCurrent) 8 | maxGlobal = maxCurrent; 9 | } 10 | return maxGlobal; 11 | }; 12 | 13 | var testArray = [1, -3, 2, 1, -1]; 14 | console.log(maxSubArray(testArray)); -------------------------------------------------------------------------------- /Problems/Arrays/medianOfTwoSortedArray.js: -------------------------------------------------------------------------------- 1 | // Helper 2 | function medianOfArray(array) { 3 | var length = array.length; 4 | 5 | // Odd 6 | if (length % 2 == 1) { 7 | return array[Math.floor(length / 2)]; 8 | } else { 9 | // Even 10 | return (array[length / 2] + array[length / 2 - 1]) / 2 11 | } 12 | } 13 | 14 | // Main 15 | function medianOfTwoSortedArray(arr1, arr2, pos) { 16 | // arr2 is the bigger array 17 | if (pos <= -1) { 18 | return -1; 19 | } 20 | if (pos == 1) { 21 | return (arr1[0] + arr2[0]) / 2; 22 | } 23 | if (pos == 2) { 24 | 25 | return (Math.max(arr1[0], arr2[0]) + Math.min(arr1[1], arr2[1])) / 2; 26 | } 27 | 28 | var median1 = medianOfArray(arr1), 29 | median2 = medianOfArray(arr2); 30 | 31 | if (median1 == median2) { 32 | return median1; 33 | } 34 | 35 | var evenOffset = pos % 2 == 0 ? 1 : 0; 36 | 37 | if (median1 < median2) { 38 | return medianOfTwoSortedArray(arr1.slice(Math.floor(pos / 2) - evenOffset), arr2, Math.floor(pos / 2) + evenOffset); 39 | } else { 40 | return medianOfTwoSortedArray(arr2.slice(Math.floor(pos / 2) - evenOffset), arr1, Math.floor(pos / 2) + evenOffset); 41 | } 42 | } 43 | 44 | console.log(medianOfTwoSortedArray([1, 2, 3], [4, 5, 6], 3)); // 3 45 | console.log(medianOfTwoSortedArray([11, 23, 24], [32, 33, 450], 3)); // 27.5 -------------------------------------------------------------------------------- /Problems/Arrays/missingNumber.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function missingNumber(nums) { 3 | var sum = nums.reduce((element1, element2) => { 4 | return element1 + element2 5 | }); 6 | // sum of 1 to n is: (n*(n+1))/2 7 | return (nums.length * (nums.length + 1)) / 2 - sum; 8 | } -------------------------------------------------------------------------------- /Problems/Arrays/partition.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamEBae/jsds/2a40b28aa729d45dea5fc5fc49d68f3311ae2455/Problems/Arrays/partition.js -------------------------------------------------------------------------------- /Problems/Arrays/pigeonHole.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function pigeonHole (arr) { 3 | var n = arr.length, 4 | hashArray = []; 5 | 6 | for (var i=0; i < n+1; i++) { 7 | hashArray.push(0); 8 | } 9 | 10 | for (var i=0; i=n) { 12 | hashArray[n]++; 13 | } else { 14 | hashArray[arr[i]]++; 15 | } 16 | } 17 | 18 | return hashArray; 19 | } 20 | 21 | console.log(pigeonHole([3, 0, 6, 1, 5])); 22 | console.log(pigeonHole([0, 1, 2, 3, 4, 5])); -------------------------------------------------------------------------------- /Problems/Arrays/subsets.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function subsets(nums) { 3 | var result = []; 4 | dfsSubset(nums.sort(), 0, [], result); 5 | return result; 6 | } 7 | 8 | function dfsSubset(nums, index, path, res) { 9 | res.push(path); 10 | for (var i = index, numsLength = nums.length; i < numsLength; i++) { 11 | dfsSubset(nums, i + 1, path.concat(nums[i]), res); 12 | } 13 | } -------------------------------------------------------------------------------- /Problems/Arrays/threeSum.js: -------------------------------------------------------------------------------- 1 | function threeSum(nums) { 2 | var result = []; 3 | nums.sort((a, b) => { 4 | return a - b 5 | }); 6 | 7 | for (var i = 0, numsLength = nums.length - 2; i < numsLength; i++) { 8 | if (i > 0 && nums[i] == nums[i - 1]) 9 | continue 10 | 11 | var left = i + 1, 12 | right = nums.length - 1; 13 | 14 | while (left < right) { 15 | var sum = nums[i] + nums[left] + nums[right]; 16 | if (sum < 0) { 17 | left++; 18 | } else if (sum > 0) { 19 | right--; 20 | } else { 21 | 22 | result.push([nums[i], nums[left], nums[right]]); 23 | 24 | while (left < right && nums[left] == nums[left + 1]) { 25 | left++; 26 | } 27 | while (left < right && nums[right] == nums[right - 1]) { 28 | right--; 29 | } 30 | left++; 31 | right--; 32 | } 33 | } 34 | } 35 | return result; 36 | } -------------------------------------------------------------------------------- /Problems/Dynamic Programming/.ipynb_checkpoints/Dynamic Programming-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Knapsack" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### Naive / Non-DP Solution" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 24, 20 | "metadata": {}, 21 | "outputs": [ 22 | { 23 | "data": { 24 | "text/plain": [ 25 | "16" 26 | ] 27 | }, 28 | "execution_count": 24, 29 | "metadata": {}, 30 | "output_type": "execute_result" 31 | } 32 | ], 33 | "source": [ 34 | "function knapsackNaiive(index, weights, values, target) {\n", 35 | " var result = 0;\n", 36 | " \n", 37 | " if (index <= -1 || target <= 0) {\n", 38 | " result = 0\n", 39 | " } else if (weights[index] > target) {\n", 40 | " result = knapsackNaiive(index-1, weights, values, target);\n", 41 | " } else {\n", 42 | " var current = knapsackNaiive(index-1, weights, values, target),\n", 43 | " currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]);\n", 44 | " result = Math.max(current, currentPlusOther);\n", 45 | " }\n", 46 | " return result;\n", 47 | "}\n", 48 | "var weights = [1,2,4,2,5],\n", 49 | " values = [5,3,5,3,2],\n", 50 | " target = 10;\n", 51 | "knapsackNaiive(4,weights, values, target);" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "### DP Solution" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 25, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "16" 70 | ] 71 | }, 72 | "execution_count": 25, 73 | "metadata": {}, 74 | "output_type": "execute_result" 75 | } 76 | ], 77 | "source": [ 78 | "function knapsackDP(index, weights, values, target, matrixDP) {\n", 79 | " var result = 0;\n", 80 | " \n", 81 | " // DP part\n", 82 | " if (matrixDP[index + '-' + target]){\n", 83 | " return matrixDP[index + '-' + target];\n", 84 | " }\n", 85 | "\n", 86 | " if (index <= -1 || target <= 0) {\n", 87 | " result = 0\n", 88 | " } else if (weights[index] > target) {\n", 89 | " result = knapsackDP(index - 1, weights, values, target, matrixDP);\n", 90 | " } else {\n", 91 | " var current = knapsackNaiive(index-1, weights, values, target),\n", 92 | " currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]);\n", 93 | " result = Math.max(current, currentPlusOther);\n", 94 | " }\n", 95 | " matrixDP[index + '-' + target] = result\n", 96 | " return result;\n", 97 | "}\n", 98 | "knapsackDP(4, weights, values, target, {});" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "## Longest Common String Length" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "### DP Solution" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 28, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "data": { 122 | "text/plain": [ 123 | "2" 124 | ] 125 | }, 126 | "execution_count": 28, 127 | "metadata": {}, 128 | "output_type": "execute_result" 129 | } 130 | ], 131 | "source": [ 132 | "function longestCommonStringLength(str1, str2) {\n", 133 | " var matrix = Array(str1.length + 1).fill(Array(str2.length + 1).fill(0)),\n", 134 | " rowLength = str1.length + 1,\n", 135 | " colLength = str2.length + 1,\n", 136 | " max = 0;\n", 137 | "\n", 138 | " for (var row = 1; row < rowLength; row++) {\n", 139 | " for (var col = 1; col < colLength; col++) {\n", 140 | " var str1Char = str1.charAt(row - 1),\n", 141 | " str2Char = str2.charAt(col - 1);\n", 142 | "\n", 143 | " if (str1Char == str2Char) {\n", 144 | " matrix[row][col] = matrix[row - 1][col - 1] + 1;\n", 145 | " max = Math.max(matrix[row][col], max);\n", 146 | " }\n", 147 | " }\n", 148 | " }\n", 149 | " return max;\n", 150 | "}\n", 151 | "longestCommonStringLength('abcd', 'bc');" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "## Coin Change" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "## Naive / Non-DP Solution" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 29, 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "data": { 175 | "text/plain": [ 176 | "4" 177 | ] 178 | }, 179 | "execution_count": 29, 180 | "metadata": {}, 181 | "output_type": "execute_result" 182 | } 183 | ], 184 | "source": [ 185 | "// Returns the count of ways we can sum coinArr which have \n", 186 | "// index like: [0,...,numCoins]\n", 187 | "function countCoinWays(coinArr, numCoins, coinValue){\n", 188 | " if (coinValue == 0) {\n", 189 | " // if the value reached zero, then only solution is \n", 190 | " // to not include any coin\n", 191 | " return 1;\n", 192 | " }\n", 193 | " if (coinValue < 0 || (numCoins<=0 && coinValue >= 1)) {\n", 194 | " // value is less than 0 means no solution\n", 195 | " // no coins left but coinValue left also means no solution\n", 196 | " return 0;\n", 197 | " }\n", 198 | " // \n", 199 | " return countCoinWays(coinArr,numCoins-1, coinValue) + \n", 200 | " countCoinWays(coinArr,numCoins, coinValue-coinArr[numCoins-1]);\n", 201 | "}\n", 202 | "function countCoinWaysWrapper(coinArr, coinValue) {\n", 203 | " return countCoinWays(coinArr, coinArr.length, coinValue);\n", 204 | "}\n", 205 | "countCoinWaysWrapper([1,2,3],4);" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "### DP Solution" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": { 219 | "collapsed": true 220 | }, 221 | "outputs": [], 222 | "source": [ 223 | "// function countCoinWaysDP(coinArr, numCoins, coinValue){\n", 224 | "// var matrix = Array(numCoins).fill(Array(coinValue+1).fill(0));\n", 225 | " \n", 226 | "// for (var i=0; i < numCoins; i++) {\n", 227 | "// matrix[0][i] = 1;\n", 228 | "// }\n", 229 | " \n", 230 | "// for (var i=1; i < coinValue+1; i++) {\n", 231 | " \n", 232 | "// for (var j=0; j < numCoins; j++) {\n", 233 | "// var x = 0,\n", 234 | "// y = 0;\n", 235 | "// if (i-)\n", 236 | "// }\n", 237 | "// }\n", 238 | "// }" 239 | ] 240 | } 241 | ], 242 | "metadata": { 243 | "kernelspec": { 244 | "display_name": "Javascript (Node.js)", 245 | "language": "javascript", 246 | "name": "javascript" 247 | }, 248 | "language_info": { 249 | "file_extension": ".js", 250 | "mimetype": "application/javascript", 251 | "name": "javascript", 252 | "version": "8.1.2" 253 | } 254 | }, 255 | "nbformat": 4, 256 | "nbformat_minor": 2 257 | } 258 | -------------------------------------------------------------------------------- /Problems/Dynamic Programming/Dynamic Programming.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Knapsack" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "### Naive / Non-DP Solution" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 24, 20 | "metadata": {}, 21 | "outputs": [ 22 | { 23 | "data": { 24 | "text/plain": [ 25 | "16" 26 | ] 27 | }, 28 | "execution_count": 24, 29 | "metadata": {}, 30 | "output_type": "execute_result" 31 | } 32 | ], 33 | "source": [ 34 | "function knapsackNaiive(index, weights, values, target) {\n", 35 | " var result = 0;\n", 36 | " \n", 37 | " if (index <= -1 || target <= 0) {\n", 38 | " result = 0\n", 39 | " } else if (weights[index] > target) {\n", 40 | " result = knapsackNaiive(index-1, weights, values, target);\n", 41 | " } else {\n", 42 | " var current = knapsackNaiive(index-1, weights, values, target),\n", 43 | " currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]);\n", 44 | " result = Math.max(current, currentPlusOther);\n", 45 | " }\n", 46 | " return result;\n", 47 | "}\n", 48 | "var weights = [1,2,4,2,5],\n", 49 | " values = [5,3,5,3,2],\n", 50 | " target = 10;\n", 51 | "knapsackNaiive(4,weights, values, target);" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "### DP Solution" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 25, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "16" 70 | ] 71 | }, 72 | "execution_count": 25, 73 | "metadata": {}, 74 | "output_type": "execute_result" 75 | } 76 | ], 77 | "source": [ 78 | "function knapsackDP(index, weights, values, target, matrixDP) {\n", 79 | " var result = 0;\n", 80 | " \n", 81 | " // DP part\n", 82 | " if (matrixDP[index + '-' + target]){\n", 83 | " return matrixDP[index + '-' + target];\n", 84 | " }\n", 85 | "\n", 86 | " if (index <= -1 || target <= 0) {\n", 87 | " result = 0\n", 88 | " } else if (weights[index] > target) {\n", 89 | " result = knapsackDP(index - 1, weights, values, target, matrixDP);\n", 90 | " } else {\n", 91 | " var current = knapsackNaiive(index-1, weights, values, target),\n", 92 | " currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]);\n", 93 | " result = Math.max(current, currentPlusOther);\n", 94 | " }\n", 95 | " matrixDP[index + '-' + target] = result\n", 96 | " return result;\n", 97 | "}\n", 98 | "knapsackDP(4, weights, values, target, {});" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "## Longest Common String Length" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "### DP Solution" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 28, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "data": { 122 | "text/plain": [ 123 | "2" 124 | ] 125 | }, 126 | "execution_count": 28, 127 | "metadata": {}, 128 | "output_type": "execute_result" 129 | } 130 | ], 131 | "source": [ 132 | "function longestCommonStringLength(str1, str2) {\n", 133 | " var matrix = Array(str1.length + 1).fill(Array(str2.length + 1).fill(0)),\n", 134 | " rowLength = str1.length + 1,\n", 135 | " colLength = str2.length + 1,\n", 136 | " max = 0;\n", 137 | "\n", 138 | " for (var row = 1; row < rowLength; row++) {\n", 139 | " for (var col = 1; col < colLength; col++) {\n", 140 | " var str1Char = str1.charAt(row - 1),\n", 141 | " str2Char = str2.charAt(col - 1);\n", 142 | "\n", 143 | " if (str1Char == str2Char) {\n", 144 | " matrix[row][col] = matrix[row - 1][col - 1] + 1;\n", 145 | " max = Math.max(matrix[row][col], max);\n", 146 | " }\n", 147 | " }\n", 148 | " }\n", 149 | " return max;\n", 150 | "}\n", 151 | "longestCommonStringLength('abcd', 'bc');" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "## Coin Change" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "## Naive / Non-DP Solution" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 29, 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "data": { 175 | "text/plain": [ 176 | "4" 177 | ] 178 | }, 179 | "execution_count": 29, 180 | "metadata": {}, 181 | "output_type": "execute_result" 182 | } 183 | ], 184 | "source": [ 185 | "// Returns the count of ways we can sum coinArr which have \n", 186 | "// index like: [0,...,numCoins]\n", 187 | "function countCoinWays(coinArr, numCoins, coinValue){\n", 188 | " if (coinValue == 0) {\n", 189 | " // if the value reached zero, then only solution is \n", 190 | " // to not include any coin\n", 191 | " return 1;\n", 192 | " }\n", 193 | " if (coinValue < 0 || (numCoins<=0 && coinValue >= 1)) {\n", 194 | " // value is less than 0 means no solution\n", 195 | " // no coins left but coinValue left also means no solution\n", 196 | " return 0;\n", 197 | " }\n", 198 | " // \n", 199 | " return countCoinWays(coinArr,numCoins-1, coinValue) + \n", 200 | " countCoinWays(coinArr,numCoins, coinValue-coinArr[numCoins-1]);\n", 201 | "}\n", 202 | "function countCoinWaysWrapper(coinArr, coinValue) {\n", 203 | " return countCoinWays(coinArr, coinArr.length, coinValue);\n", 204 | "}\n", 205 | "countCoinWaysWrapper([1,2,3],4);" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "### DP Solution" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": { 219 | "collapsed": true 220 | }, 221 | "outputs": [], 222 | "source": [ 223 | "// function countCoinWaysDP(coinArr, numCoins, coinValue){\n", 224 | "// var matrix = Array(numCoins).fill(Array(coinValue+1).fill(0));\n", 225 | " \n", 226 | "// for (var i=0; i < numCoins; i++) {\n", 227 | "// matrix[0][i] = 1;\n", 228 | "// }\n", 229 | " \n", 230 | "// for (var i=1; i < coinValue+1; i++) {\n", 231 | " \n", 232 | "// for (var j=0; j < numCoins; j++) {\n", 233 | "// var x = 0,\n", 234 | "// y = 0;\n", 235 | "// if (i-)\n", 236 | "// }\n", 237 | "// }\n", 238 | "// }" 239 | ] 240 | } 241 | ], 242 | "metadata": { 243 | "kernelspec": { 244 | "display_name": "Javascript (Node.js)", 245 | "language": "javascript", 246 | "name": "javascript" 247 | }, 248 | "language_info": { 249 | "file_extension": ".js", 250 | "mimetype": "application/javascript", 251 | "name": "javascript", 252 | "version": "8.1.2" 253 | } 254 | }, 255 | "nbformat": 4, 256 | "nbformat_minor": 2 257 | } 258 | -------------------------------------------------------------------------------- /Problems/Dynamic Programming/countCoinWays.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function Matrix(rows, columns) { 3 | var jaggedarray = new Array(rows); 4 | for (var i = 0; i < columns; i += 1) { 5 | jaggedarray[i] = new Array(rows); 6 | } 7 | return jaggedarray; 8 | } 9 | 10 | // Main 11 | // Non-DP solution 12 | 13 | 14 | // Returns the count of ways we can sum coinArr which have 15 | // index like: [0,...,numCoins] 16 | function countCoinWays(coinArr, numCoins, coinValue) { 17 | if (coinValue == 0) { 18 | // if the value reached zero, then only solution is 19 | // to not include any coin 20 | return 1; 21 | } 22 | if (coinValue < 0 || (numCoins <= 0 && coinValue >= 1)) { 23 | // value is less than 0 means no solution 24 | // no coins left but coinValue left also means no solution 25 | return 0; 26 | } 27 | // 28 | return countCoinWays(coinArr, numCoins - 1, coinValue) + 29 | countCoinWays(coinArr, numCoins, coinValue - coinArr[numCoins - 1]); 30 | } 31 | 32 | function countCoinWaysWrapper(coinArr, coinValue) { 33 | return countCoinWays(coinArr, coinArr.length, coinValue); 34 | } 35 | countCoinWaysWrapper([1, 2, 3], 4); // 4 36 | 37 | 38 | // DP solution 39 | function countCoinWaysDP(coinArr, numCoins, coinValue) { 40 | var matrix = Matrix(numCoins, coinValue + 1); 41 | 42 | // filling the matrix for 0 case (ie coinValue = 0) 43 | for (var i = 0; i < numCoins; i++) { 44 | matrix[0][i] = 1; 45 | } 46 | 47 | // fill rest bottom-up 48 | for (var i = 1; i < coinValue + 1; i++) { 49 | for (var j = 0; j < numCoins; j++) { 50 | var x = 0, 51 | y = 0; 52 | if (i - coinArr[j] >= 0) { 53 | x = matrix[i - coinArr[j]][j]; 54 | } 55 | if (j >= 1) { 56 | y = matrix[i][j - 1] 57 | } 58 | matrix[i][j] = x + y; 59 | } 60 | } 61 | 62 | return matrix[coinValue][numCoins - 1]; 63 | } 64 | 65 | function countCoinWaysDPWrapper(coinArr, coinValue) { 66 | return countCoinWaysDP(coinArr, coinArr.length, coinValue); 67 | } 68 | countCoinWaysDP([1, 2, 3], 3, 4); // 4 -------------------------------------------------------------------------------- /Problems/Dynamic Programming/knapsackDP.js: -------------------------------------------------------------------------------- 1 | function knapsackDP(index, weights, values, target, matrixDP) { 2 | var result = 0; 3 | 4 | // DP part 5 | if (matrixDP[index + '-' + target]){ 6 | return matrixDP[index + '-' + target]; 7 | } 8 | 9 | if (index <= -1 || target <= 0) { 10 | result = 0 11 | } else if (weights[index] > target) { 12 | result = knapsackDP(index - 1, weights, values, target, matrixDP); 13 | } else { 14 | var current = knapsackNaiive(index-1, weights, values, target), 15 | currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]); 16 | result = Math.max(current, currentPlusOther); 17 | } 18 | matrixDP[index + '-' + target] = result 19 | return result; 20 | } 21 | 22 | var weights = [1, 2, 4, 2, 5]; 23 | var values = [5, 3, 5, 3, 2]; 24 | var target = 10; 25 | var matrixDP = {}; 26 | 27 | console.log(knapsackDP(4, weights, values, target, matrixDP)); // 16 -------------------------------------------------------------------------------- /Problems/Dynamic Programming/knapsackNaiive.js: -------------------------------------------------------------------------------- 1 | function knapsackNaiive(index, weights, values, target) { 2 | var result = 0; 3 | 4 | if (index <= -1 || target <= 0) { 5 | result = 0 6 | } else if (weights[index] > target) { 7 | result = knapsackNaiive(index-1, weights, values, target); 8 | } else { 9 | var current = knapsackNaiive(index-1, weights, values, target), 10 | currentPlusOther = values[index] + knapsackNaiive(index-1, weights, values, target - weights[index]); 11 | result = Math.max(current, currentPlusOther); 12 | } 13 | return result; 14 | } 15 | 16 | var weights = [1,2,4,2,5]; 17 | var values = [5,3,5,3,2]; 18 | var target = 10; 19 | console.log(knapsackNaiive(4,weights, values, target)); -------------------------------------------------------------------------------- /Problems/Dynamic Programming/longestString.js: -------------------------------------------------------------------------------- 1 | function longestCommonStringLength(str1, str2) { 2 | var matrix = Array(str1.length + 1).fill(Array(str2.length + 1).fill(0)), 3 | rowLength = str1.length + 1, 4 | colLength = str2.length + 1, 5 | max = 0; 6 | 7 | for (var row = 1; row < rowLength; row++) { 8 | for (var col = 1; col < colLength; col++) { 9 | var str1Char = str1.charAt(row - 1), 10 | str2Char = str2.charAt(col - 1); 11 | 12 | if (str1Char == str2Char) { 13 | matrix[row][col] = matrix[row - 1][col - 1] + 1; 14 | max = Math.max(matrix[row][col], max); 15 | } 16 | } 17 | } 18 | return max; 19 | } 20 | longestCommonStringLength('abcd', 'bc'); // 2 -------------------------------------------------------------------------------- /Problems/Heaps/MedianHeap.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | // Helper 3 | function Heap() { 4 | this.content = []; 5 | this.scoreFunction = function(val) { 6 | return val; 7 | } 8 | } 9 | 10 | Heap.prototype.size = function() { 11 | return this.content.length; 12 | } 13 | 14 | Heap.prototype.push = function(a) { 15 | this.content.push(a); 16 | this.bubbleUp(this.content.length - 1); 17 | } 18 | 19 | Heap.prototype.pop = function() { 20 | var a = this.content[0]; 21 | var b = this.content.pop(); 22 | if (this.content.length > 0) { 23 | this.content[0] = b; 24 | this.sinkDown(0); 25 | } 26 | return a; 27 | } 28 | 29 | Heap.prototype.remove = function(a) { 30 | var b = this.content.length; 31 | for (var c = 0; c < b; c++) { 32 | if (this.content[c] != a) continue; 33 | var d = this.content.pop(); 34 | if (c == b - 1) break; 35 | this.content[c] = d; 36 | this.bubbleUp(c); 37 | this.sinkDown(c); 38 | break; 39 | } 40 | } 41 | 42 | 43 | // Main 44 | function MinHeap() { 45 | Heap.call(this); 46 | } 47 | 48 | MinHeap.prototype = new Heap(); // inherit methods 49 | 50 | MinHeap.prototype.bubbleUp = function(n) { 51 | // Fetch the element that has to be moved. 52 | var element = this.content[n], 53 | score = this.scoreFunction(element); 54 | // When at 0, an element can not go up any further. 55 | while (n > 0) { 56 | // Compute the parent element's index, and fetch it. 57 | var parentN = Math.floor((n + 1) / 2) - 1, 58 | parent = this.content[parentN]; 59 | // If the parent has a lesser score, things are in order and we 60 | // are done. 61 | if (score >= this.scoreFunction(parent)) 62 | break; 63 | 64 | // Otherwise, swap the parent with the current element and 65 | // continue. 66 | this.content[parentN] = element; 67 | this.content[n] = parent; 68 | n = parentN; 69 | } 70 | } 71 | 72 | MinHeap.prototype.sinkDown = function(n) { 73 | // Look up the target element and its score. 74 | var length = this.content.length, 75 | element = this.content[n], 76 | elemScore = this.scoreFunction(element); 77 | 78 | while (true) { 79 | // Compute the indices of the child elements. 80 | var child2N = (n + 1) * 2, 81 | child1N = child2N - 1; 82 | // This is used to store the new position of the element, 83 | // if any. 84 | var swap = null; 85 | // If the first child exists (is inside the array)... 86 | if (child1N < length) { 87 | // Look it up and compute its score. 88 | var child1 = this.content[child1N], 89 | child1Score = this.scoreFunction(child1); 90 | // If the score is less than our element's, we need to swap. 91 | if (child1Score < elemScore) 92 | swap = child1N; 93 | } 94 | // Do the same checks for the other child. 95 | if (child2N < length) { 96 | var child2 = this.content[child2N], 97 | child2Score = this.scoreFunction(child2); 98 | if (child2Score < (swap == null ? elemScore : child1Score)) 99 | swap = child2N; 100 | } 101 | 102 | // No need to swap further, we are done. 103 | if (swap == null) break; 104 | 105 | // Otherwise, swap and continue. 106 | this.content[n] = this.content[swap]; 107 | this.content[swap] = element; 108 | n = swap; 109 | } 110 | } 111 | 112 | Heap.prototype.size = function() { 113 | return this.content.length; 114 | } 115 | 116 | Heap.prototype.push = function(a) { 117 | this.content.push(a); 118 | this.bubbleUp(this.content.length - 1); 119 | } 120 | 121 | Heap.prototype.pop = function() { 122 | var a = this.content[0]; 123 | var b = this.content.pop(); 124 | if (this.content.length > 0) { 125 | this.content[0] = b; 126 | this.sinkDown(0); 127 | } 128 | return a; 129 | } 130 | 131 | Heap.prototype.remove = function(a) { 132 | var b = this.content.length; 133 | for (var c = 0; c < b; c++) { 134 | if (this.content[c] != a) continue; 135 | var d = this.content.pop(); 136 | if (c == b - 1) break; 137 | this.content[c] = d; 138 | this.bubbleUp(c); 139 | this.sinkDown(c); 140 | break; 141 | } 142 | } 143 | 144 | // Main 145 | function MaxHeap() { 146 | Heap.call(this); 147 | } 148 | 149 | MaxHeap.prototype = new Heap(); 150 | 151 | MaxHeap.prototype.bubbleUp = function(n) { 152 | // Fetch the element that has to be moved. 153 | var element = this.content[n], 154 | score = this.scoreFunction(element); 155 | // When at 0, an element can not go up any further. 156 | while (n > 0) { 157 | // Compute the parent element's index, and fetch it. 158 | var parentN = Math.floor((n + 1) / 2) - 1, 159 | parent = this.content[parentN]; 160 | // If the parent has a larger score, things are in order and we 161 | // are done. 162 | if (score <= this.scoreFunction(parent)) 163 | break; 164 | 165 | // Otherwise, swap the parent with the current element and 166 | // continue. 167 | this.content[parentN] = element; 168 | this.content[n] = parent; 169 | n = parentN; 170 | } 171 | } 172 | 173 | MaxHeap.prototype.sinkDown = function(n) { 174 | // Look up the target element and its score. 175 | var length = this.content.length, 176 | element = this.content[n], 177 | elemScore = this.scoreFunction(element); 178 | 179 | while (true) { 180 | // Compute the indices of the child elements. 181 | var child2N = (n + 1) * 2, 182 | child1N = child2N - 1; 183 | // This is used to store the new position of the element, 184 | // if any. 185 | var swap = null; 186 | // If the first child exists (is inside the array)... 187 | if (child1N < length) { 188 | // Look it up and compute its score. 189 | var child1 = this.content[child1N], 190 | child1Score = this.scoreFunction(child1); 191 | // If the score is larger than our element's, we need to swap. 192 | if (child1Score > elemScore) 193 | swap = child1N; 194 | } 195 | // Do the same checks for the other child. 196 | if (child2N < length) { 197 | var child2 = this.content[child2N], 198 | child2Score = this.scoreFunction(child2); 199 | if (child2Score > (swap == null ? elemScore : child1Score)) 200 | swap = child2N; 201 | } 202 | 203 | // No need to swap further, we are done. 204 | if (swap == null) break; 205 | 206 | // Otherwise, swap and continue. 207 | this.content[n] = this.content[swap]; 208 | this.content[swap] = element; 209 | n = swap; 210 | } 211 | } 212 | 213 | // Main 214 | function MedianHeap() { 215 | this.minHeap = new MinHeap(); 216 | this.maxHeap = new MaxHeap(); 217 | } 218 | MedianHeap.prototype.push = function(value) { 219 | if (value > this.median()) { 220 | this.minHeap.push(value); 221 | } else { 222 | this.maxHeap.push(value); 223 | } 224 | 225 | // Re balancing 226 | if (this.minHeap.size() - this.maxHeap.size() > 1) { 227 | this.maxHeap.push(this.minHeap.pop()); 228 | } 229 | 230 | if (this.maxHeap.size() - this.minHeap.size() > 1) { 231 | this.minHeap.push(this.maxHeap.pop()); 232 | } 233 | } 234 | MedianHeap.prototype.median = function() { 235 | if (this.minHeap.size() == 0 && this.maxHeap.size() == 0) { 236 | return Number.NEGATIVE_INFINITY; 237 | } else if (this.minHeap.size() == this.maxHeap.size()) { 238 | return (this.minHeap.content[0] + this.maxHeap.content[0]) / 2; 239 | } else if (this.minHeap.size() > this.maxHeap.size()) { 240 | return this.minHeap.content[0]; 241 | } else { 242 | return this.maxHeap.content[0]; 243 | } 244 | } 245 | 246 | var medianH = new MedianHeap(); 247 | 248 | medianH.push(12); 249 | console.log(medianH.median()); // 12 250 | medianH.push(2); 251 | console.log(medianH.median()); // 7 ( because 12 + 2 = 14; 14/2 = 7) 252 | medianH.push(23); 253 | console.log(medianH.median()); // 12 254 | medianH.push(13); 255 | console.log(medianH.median()); // 12.5 -------------------------------------------------------------------------------- /Problems/Heaps/getKthBiggestElement.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | // Helpers 3 | function Heap() { 4 | this.content = []; 5 | this.scoreFunction = function(val) { 6 | return val; 7 | } 8 | } 9 | 10 | Heap.prototype.size = function() { 11 | return this.content.length; 12 | } 13 | 14 | Heap.prototype.push = function(a) { 15 | this.content.push(a); 16 | this.bubbleUp(this.content.length - 1); 17 | } 18 | 19 | Heap.prototype.pop = function() { 20 | var a = this.content[0]; 21 | var b = this.content.pop(); 22 | if (this.content.length > 0) { 23 | this.content[0] = b; 24 | this.sinkDown(0); 25 | } 26 | return a; 27 | } 28 | 29 | Heap.prototype.remove = function(a) { 30 | var b = this.content.length; 31 | for (var c = 0; c < b; c++) { 32 | if (this.content[c] != a) continue; 33 | var d = this.content.pop(); 34 | if (c == b - 1) break; 35 | this.content[c] = d; 36 | this.bubbleUp(c); 37 | this.sinkDown(c); 38 | break; 39 | } 40 | } 41 | 42 | // Main 43 | function MaxHeap() { 44 | Heap.call(this); 45 | } 46 | 47 | MaxHeap.prototype = new Heap(); 48 | 49 | MaxHeap.prototype.bubbleUp = function(n) { 50 | // Fetch the element that has to be moved. 51 | var element = this.content[n], 52 | score = this.scoreFunction(element); 53 | // When at 0, an element can not go up any further. 54 | while (n > 0) { 55 | // Compute the parent element's index, and fetch it. 56 | var parentN = Math.floor((n + 1) / 2) - 1, 57 | parent = this.content[parentN]; 58 | // If the parent has a larger score, things are in order and we 59 | // are done. 60 | if (score <= this.scoreFunction(parent)) 61 | break; 62 | 63 | // Otherwise, swap the parent with the current element and 64 | // continue. 65 | this.content[parentN] = element; 66 | this.content[n] = parent; 67 | n = parentN; 68 | } 69 | } 70 | 71 | MaxHeap.prototype.sinkDown = function(n) { 72 | // Look up the target element and its score. 73 | var length = this.content.length, 74 | element = this.content[n], 75 | elemScore = this.scoreFunction(element); 76 | 77 | while (true) { 78 | // Compute the indices of the child elements. 79 | var child2N = (n + 1) * 2, 80 | child1N = child2N - 1; 81 | // This is used to store the new position of the element, 82 | // if any. 83 | var swap = null; 84 | // If the first child exists (is inside the array)... 85 | if (child1N < length) { 86 | // Look it up and compute its score. 87 | var child1 = this.content[child1N], 88 | child1Score = this.scoreFunction(child1); 89 | // If the score is larger than our element's, we need to swap. 90 | if (child1Score > elemScore) 91 | swap = child1N; 92 | } 93 | // Do the same checks for the other child. 94 | if (child2N < length) { 95 | var child2 = this.content[child2N], 96 | child2Score = this.scoreFunction(child2); 97 | if (child2Score > (swap == null ? elemScore : child1Score)) 98 | swap = child2N; 99 | } 100 | 101 | // No need to swap further, we are done. 102 | if (swap == null) break; 103 | 104 | // Otherwise, swap and continue. 105 | this.content[n] = this.content[swap]; 106 | this.content[swap] = element; 107 | n = swap; 108 | } 109 | } 110 | 111 | // Main 112 | function getKthBiggestElement(array, k) { 113 | var maxH = new MaxHeap(); 114 | for (var i = 0, arrayLength = array.length; i < arrayLength; i++) { 115 | maxH.push(array[i]); 116 | } 117 | for (var i = 1; i < k; i++) { 118 | maxH.pop(); 119 | } 120 | return maxH.pop(); 121 | } 122 | 123 | var array1 = [12, 3, 13, 4, 2, 40, 23]; 124 | console.log(getKthBiggestElement(array1, 2)); // 23 125 | console.log(getKthBiggestElement(array1, 1)); // 40 126 | console.log(getKthBiggestElement(array1, 7)); // 2 -------------------------------------------------------------------------------- /Problems/Heaps/getKthSmallestElement.js: -------------------------------------------------------------------------------- 1 | // Helper 2 | function Heap() { 3 | this.content = []; 4 | this.scoreFunction = function(val) { 5 | return val; 6 | } 7 | } 8 | 9 | Heap.prototype.size = function() { 10 | return this.content.length; 11 | } 12 | 13 | Heap.prototype.push = function(a) { 14 | this.content.push(a); 15 | this.bubbleUp(this.content.length - 1); 16 | } 17 | 18 | Heap.prototype.pop = function() { 19 | var a = this.content[0]; 20 | var b = this.content.pop(); 21 | if (this.content.length > 0) { 22 | this.content[0] = b; 23 | this.sinkDown(0); 24 | } 25 | return a; 26 | } 27 | 28 | Heap.prototype.remove = function(a) { 29 | var b = this.content.length; 30 | for (var c = 0; c < b; c++) { 31 | if (this.content[c] != a) continue; 32 | var d = this.content.pop(); 33 | if (c == b - 1) break; 34 | this.content[c] = d; 35 | this.bubbleUp(c); 36 | this.sinkDown(c); 37 | break; 38 | } 39 | } 40 | 41 | 42 | // Main 43 | function MinHeap() { 44 | Heap.call(this); 45 | } 46 | 47 | MinHeap.prototype = new Heap(); // inherit methods 48 | 49 | MinHeap.prototype.bubbleUp = function(n) { 50 | // Fetch the element that has to be moved. 51 | var element = this.content[n], 52 | score = this.scoreFunction(element); 53 | // When at 0, an element can not go up any further. 54 | while (n > 0) { 55 | // Compute the parent element's index, and fetch it. 56 | var parentN = Math.floor((n + 1) / 2) - 1, 57 | parent = this.content[parentN]; 58 | // If the parent has a lesser score, things are in order and we 59 | // are done. 60 | if (score >= this.scoreFunction(parent)) 61 | break; 62 | 63 | // Otherwise, swap the parent with the current element and 64 | // continue. 65 | this.content[parentN] = element; 66 | this.content[n] = parent; 67 | n = parentN; 68 | } 69 | } 70 | 71 | MinHeap.prototype.sinkDown = function(n) { 72 | // Look up the target element and its score. 73 | var length = this.content.length, 74 | element = this.content[n], 75 | elemScore = this.scoreFunction(element); 76 | 77 | while (true) { 78 | // Compute the indices of the child elements. 79 | var child2N = (n + 1) * 2, 80 | child1N = child2N - 1; 81 | // This is used to store the new position of the element, 82 | // if any. 83 | var swap = null; 84 | // If the first child exists (is inside the array)... 85 | if (child1N < length) { 86 | // Look it up and compute its score. 87 | var child1 = this.content[child1N], 88 | child1Score = this.scoreFunction(child1); 89 | // If the score is less than our element's, we need to swap. 90 | if (child1Score < elemScore) 91 | swap = child1N; 92 | } 93 | // Do the same checks for the other child. 94 | if (child2N < length) { 95 | var child2 = this.content[child2N], 96 | child2Score = this.scoreFunction(child2); 97 | if (child2Score < (swap == null ? elemScore : child1Score)) 98 | swap = child2N; 99 | } 100 | 101 | // No need to swap further, we are done. 102 | if (swap == null) break; 103 | 104 | // Otherwise, swap and continue. 105 | this.content[n] = this.content[swap]; 106 | this.content[swap] = element; 107 | n = swap; 108 | } 109 | } 110 | 111 | function getKthSmallestElement(array, k) { 112 | var minH = new MinHeap(); 113 | for (var i = 0, arrayLength = array.length; i < arrayLength; i++) { 114 | minH.push(array[i]); 115 | } 116 | for (var i = 1; i < k; i++) { 117 | minH.pop(); 118 | } 119 | return minH.pop(); 120 | } 121 | 122 | var array1 = [12, 3, 13, 4, 2, 40, 23]; 123 | 124 | console.log(getKthSmallestElement(array1, 2)); // 3 125 | console.log(getKthSmallestElement(array1, 1)); // 2 126 | console.log(getKthSmallestElement(array1, 7)); // 40 -------------------------------------------------------------------------------- /Problems/LinkedLists/deleteDuplicates.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function linkedListToString(node) { 3 | var convertedString = '' 4 | while (node) { 5 | convertedString += ' ' + node.value; 6 | node = node.next; 7 | } 8 | return convertedString; 9 | } 10 | 11 | // Main 12 | function deleteDuplicates(node) { 13 | var trackDict = {}, 14 | prev = null; 15 | 16 | while (node) { 17 | // check if seen before: 18 | if (trackDict[node.value]) { 19 | prev.next = node.next; 20 | } else { 21 | trackDict[node.value] = true; 22 | prev = node; 23 | } 24 | node = node.next; 25 | } 26 | } 27 | 28 | // this node has a duplicate. 2 is repeated: 29 | var node1 = { 30 | value: 1, 31 | next: { 32 | value: 2, 33 | next: { 34 | value: 2, 35 | next: { 36 | value: 4, 37 | next: { 38 | value: 5 39 | } 40 | } 41 | } 42 | } 43 | } 44 | 45 | console.log(linkedListToString(node1)); // 1 2 2 4 5 46 | deleteDuplicates(node1); 47 | console.log(linkedListToString(node1)); // 1 2 4 5 -------------------------------------------------------------------------------- /Problems/LinkedLists/deleteNode.js: -------------------------------------------------------------------------------- 1 | // Helpers: 2 | function linkedListToString(node) { 3 | var convertedString = '' 4 | while (node) { 5 | convertedString += ' ' + node.value; 6 | node = node.next; 7 | } 8 | return convertedString; 9 | } 10 | 11 | // Main 12 | function deleteNode(node) { 13 | // deletes node given only that node for linked list 14 | var temp = node.next; 15 | node.value = temp.value; 16 | node.next = temp.next; 17 | } 18 | 19 | 20 | // Tests 21 | var ll1 = { 22 | value: 1, 23 | next: { 24 | value: 2, 25 | next: { 26 | value: 3, 27 | next: { 28 | value: 4, 29 | next: null 30 | } 31 | } 32 | } 33 | } 34 | 35 | var ll2 = { 36 | value: 1, 37 | next: { 38 | value: 0, 39 | next: { 40 | value: 2, 41 | next: null 42 | } 43 | } 44 | } 45 | 46 | console.log(linkedListToString(ll1)); // 1 2 3 4 47 | deleteNode(ll1.next.next); 48 | console.log(linkedListToString(ll1)); // 1 2 4 49 | 50 | console.log(linkedListToString(ll2)); // 1 0 2 51 | deleteNode(ll2.next); 52 | console.log(linkedListToString(ll2)); // 1 2 -------------------------------------------------------------------------------- /Problems/LinkedLists/findMergePoint.js: -------------------------------------------------------------------------------- 1 | function findMergePoint(node1, node2) { 2 | var tempNode1 = Object.create(node1), 3 | tempNode2 = Object.create(node2); 4 | 5 | while (tempNode1.value != tempNode2.value) { 6 | if (!tempNode1.next) { 7 | tempNode1 = node2; 8 | } else { 9 | tempNode1 = tempNode1.next; 10 | } 11 | 12 | if (!tempNode2.next) { 13 | tempNode2 = node1; 14 | } else { 15 | tempNode2 = tempNode2.next; 16 | } 17 | } 18 | 19 | return tempNode1.next; 20 | } 21 | 22 | var node1 = { 23 | value: 1, 24 | next: { 25 | value: 2, 26 | next: { 27 | value: 3, 28 | next: { 29 | value: 4, 30 | next: { 31 | value: 5 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | var node2 = { 39 | value: 3, 40 | next: { 41 | value: 4 42 | } 43 | } 44 | 45 | // node1 and node2 merges at 3 -> 4 46 | 47 | console.log(findMergePoint(node1, node2)); // 4 -------------------------------------------------------------------------------- /Problems/LinkedLists/findMiddlePoint.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function findMiddlePoint(head) { 3 | if (head == null) 4 | return null; 5 | 6 | var temp = head, 7 | fast = temp, 8 | slow = head; 9 | 10 | while (fast != null && fast.next != null) { 11 | slow = slow.next; 12 | fast = fast.next.next; 13 | } 14 | return slow; 15 | } 16 | 17 | var ll1 = { 18 | value: 1, 19 | next: { 20 | value: 2, 21 | next: { 22 | value: 3, 23 | next: { 24 | value: 5, 25 | next: { 26 | value: 17, 27 | next: { 28 | value: 21 29 | } 30 | } 31 | } 32 | } 33 | } 34 | }; 35 | 36 | console.log(findMiddlePoint(ll1)); // ll1 starting with 5 -------------------------------------------------------------------------------- /Problems/LinkedLists/isPalindrome.js: -------------------------------------------------------------------------------- 1 | // Helper 2 | function reverseSinglyLinkedList(node) { 3 | var prev = null; 4 | 5 | while (node) { 6 | var temp = node.next; 7 | node.next = prev; 8 | prev = node; 9 | if (!temp) 10 | break; 11 | node = temp; 12 | } 13 | return node; 14 | } 15 | 16 | function findMiddlePoint(head) { 17 | if (head == null) 18 | return null; 19 | 20 | var temp = head, 21 | fast = temp, 22 | slow = head; 23 | 24 | while (fast != null && fast.next != null) { 25 | slow = slow.next; 26 | fast = fast.next.next; 27 | } 28 | return slow; 29 | } 30 | 31 | // Main 32 | var isPalindrome = function(head) { 33 | if (head == null) { 34 | return true; 35 | } 36 | 37 | var tempHead = head, 38 | midPoint = findMiddlePoint(tempHead), 39 | latterReversed = reverseSinglyLinkedList(midPoint); 40 | 41 | while (latterReversed != null) { 42 | if (latterReversed.val != tempHead.val) 43 | return false; 44 | 45 | latterReversed = latterReversed.next; 46 | tempHead = tempHead.next; 47 | } 48 | return true; 49 | } -------------------------------------------------------------------------------- /Problems/LinkedLists/linkedListToString.js: -------------------------------------------------------------------------------- 1 | function linkedListToString(node) { 2 | var convertedString = '' 3 | while (node) { 4 | convertedString += ' ' + node.value; 5 | node = node.next; 6 | } 7 | return convertedString; 8 | } 9 | 10 | var node1 = { 11 | value: 1, 12 | next: { 13 | value: 2, 14 | next: { 15 | value: 3, 16 | next: { 17 | value: 4, 18 | next: { 19 | value: 5 20 | } 21 | } 22 | } 23 | } 24 | } 25 | 26 | console.log(linkedListToString(node1)); // 1 2 3 4 5 -------------------------------------------------------------------------------- /Problems/LinkedLists/mergeIteratively.js: -------------------------------------------------------------------------------- 1 | function mergeInteratively(l1, l2) { 2 | var l = { 3 | value: 0, 4 | next: null 5 | }; 6 | var p = l; 7 | 8 | while (l1 != null && l2 != null) { 9 | if (l1.value < l2.value) { 10 | p.next = l1; 11 | l1 = l1.next; 12 | } else { 13 | p.next = l2; 14 | l2 = l2.next; 15 | } 16 | p = p.next; 17 | } 18 | 19 | if (l1 != null) 20 | p.next = l1; 21 | 22 | if (l2 != null) 23 | p.next = l2; 24 | 25 | return l.next; 26 | } 27 | 28 | 29 | var ll1 = { 30 | value: 1, 31 | next: { 32 | value: 2, 33 | next: { 34 | value: 3, 35 | next: { 36 | value: 5 37 | } 38 | } 39 | } 40 | }; 41 | var ll2 = { 42 | value: 4, 43 | next: { 44 | value: 6 45 | } 46 | }; 47 | 48 | console.log(mergeInteratively(ll1, ll2)); // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -------------------------------------------------------------------------------- /Problems/LinkedLists/mergeRecursively.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function mergeSortedLinkedListRecursively(a, b) { 3 | if (a == null) { 4 | return b; 5 | } 6 | if (b == null) { 7 | return a; 8 | } 9 | 10 | if (a.value < b.value) { 11 | a.next = mergeSortedLinkedListRecursively(a.next, b); 12 | return a; 13 | } else { 14 | b.next = mergeSortedLinkedListRecursively(b.next, a); 15 | return b; 16 | } 17 | } 18 | 19 | var ll1 = { 20 | value: 1, 21 | next: { 22 | value: 2, 23 | next: { 24 | value: 3, 25 | next: { 26 | value: 5 27 | } 28 | } 29 | } 30 | }; 31 | var ll2 = { 32 | value: 4, 33 | next: { 34 | value: 6 35 | } 36 | }; 37 | 38 | console.log(mergeSortedLinkedListRecursively(ll1, ll2)); // 1 -> 2 -> 3 -> 4 -> 5 -> 6 -------------------------------------------------------------------------------- /Problems/LinkedLists/reverseLinkedList.js: -------------------------------------------------------------------------------- 1 | // Helpers: 2 | function linkedListToString(node) { 3 | var convertedString = '' 4 | while (node) { 5 | convertedString += ' ' + node.value; 6 | node = node.next; 7 | } 8 | return convertedString; 9 | } 10 | 11 | // Main: 12 | function reverseSinglyLinkedList(node) { 13 | var prev = null; 14 | 15 | while (node) { 16 | var temp = node.next; 17 | node.next = prev; 18 | prev = node; 19 | if (!temp) 20 | break; 21 | node = temp; 22 | } 23 | return node; 24 | } 25 | 26 | var node1 = { 27 | value: 1, 28 | next: { 29 | value: 2, 30 | next: { 31 | value: 3, 32 | next: { 33 | value: 4, 34 | next: { 35 | value: 5 36 | } 37 | } 38 | } 39 | } 40 | } 41 | 42 | var node1Reversed = { 43 | value: 5, 44 | next: { 45 | value: 4, 46 | next: { 47 | value: 3, 48 | next: { 49 | value: 2, 50 | next: { 51 | value: 1 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | console.log(linkedListToString(node1)); // 1 2 3 4 5 59 | var revesedNode = reverseSinglyLinkedList(node1); 60 | console.log(linkedListToString(revesedNode)); // 5 4 3 2 1 -------------------------------------------------------------------------------- /Problems/LinkedLists/sortLinkedList.js: -------------------------------------------------------------------------------- 1 | // Helper 2 | function mergeSortedLinkedListRecursively(a, b) { 3 | if (a == null) { 4 | return b; 5 | } 6 | if (b == null) { 7 | return a; 8 | } 9 | 10 | if (a.value < b.value) { 11 | a.next = mergeSortedLinkedListRecursively(a.next, b); 12 | return a; 13 | } else { 14 | b.next = mergeSortedLinkedListRecursively(b.next, a); 15 | return b; 16 | } 17 | } 18 | 19 | var ll1 = { 20 | value: 712, 21 | next: { 22 | value: 213, 23 | next: { 24 | value: 1230, 25 | next: { 26 | value: 5 27 | } 28 | } 29 | } 30 | }; 31 | 32 | // Main 33 | function sortLinkedList(head) { 34 | if (head == null || head.next == null) { 35 | return head; 36 | } 37 | 38 | // Step 1. cut the list to two halves 39 | var prev = null, 40 | slow = head, 41 | fast = head; 42 | 43 | while (fast != null && fast.next != null) { 44 | prev = slow; 45 | slow = slow.next; 46 | fast = fast.next.next; 47 | } 48 | 49 | prev.next = null; 50 | 51 | // Step 2. sort each half 52 | var l1 = sortLinkedList(head), 53 | l2 = sortLinkedList(slow); 54 | 55 | // Step 3. merge l1 and l2 56 | return mergeSortedLinkedListRecursively(l1, l2); 57 | } 58 | 59 | // before: 712 -> 213 -> 1230 -> 5 60 | console.log(sortLinkedList(ll1)); // after: 5->213->712->1230 -------------------------------------------------------------------------------- /Problems/MultiDimensionalArrays/mazePathFinder.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function generateColumnArr(arr) { 3 | return arr.split(""); 4 | } 5 | 6 | function printMatrix(matrix) { 7 | var mazePrintStr = "", 8 | row = matrix.length, 9 | column = matrix[0].length; 10 | 11 | for (var i = 0; i < row; i++) { 12 | 13 | for (var j = 0; j < column; j++) { 14 | mazePrintStr += mazeMatrix[i][j]; 15 | } 16 | 17 | mazePrintStr += "\n"; 18 | 19 | } 20 | console.log(mazePrintStr); 21 | } 22 | 23 | // Main 24 | function mazePathFinder(mazeMatrix) { 25 | var row = mazeMatrix.length, 26 | column = mazeMatrix[0].length, 27 | startPos = findChar('e'), 28 | endPos = findChar('x') 29 | 30 | function findChar(char) { 31 | for (var i = 0; i < row; i++) { 32 | for (var j = 0; j < column; j++) { 33 | if (mazeMatrix[i][j] == char) { 34 | return [i, j]; 35 | } 36 | } 37 | } 38 | } 39 | 40 | path(startPos[0], startPos[1]); 41 | 42 | function path(x, y) { 43 | if (x > row - 1 || y > column - 1 || x < 0 || y < 0) { 44 | return false; 45 | } 46 | if (x == endPos[0] && y == endPos[1]) { 47 | return true; 48 | } 49 | if (mazeMatrix[x][y] == '%' || mazeMatrix[x][y] == '+') { 50 | return false; 51 | } 52 | // Mark the current spot 53 | mazeMatrix[x][y] = '+'; 54 | 55 | printMatrix(mazeMatrix); 56 | 57 | if (path(x, y - 1) == true) { 58 | return true; 59 | } 60 | if (path(x + 1, y) == true) { 61 | return true; 62 | } 63 | if (path(x, y + 1) == true) { 64 | return true; 65 | } 66 | if (path(x - 1, y) == true) { 67 | return true; 68 | } 69 | mazeMatrix[x][y] = '.'; 70 | return false; 71 | } 72 | } 73 | 74 | var mazeMatrix = "%e%%%%%%%%%\n%...%.%...%\n%.%.%.%.%%%\n%.%.......%\n%.%%%%.%%.%\n%.%\.....%.%\n%%%%%%%%%x%".split("\n").map(generateColumnArr); 75 | mazePathFinder(mazeMatrix); -------------------------------------------------------------------------------- /Problems/MultiDimensionalArrays/rotateMatrix.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function rotateMatrix90Left(mat) { 3 | var N = mat.length; 4 | 5 | // Consider all squares one by one 6 | for (var x = 0; x < N / 2; x++) { 7 | // Consider elements in group of 4 in 8 | // current square 9 | for (var y = x; y < N - x - 1; y++) { 10 | // store current cell in temp variable 11 | var temp = mat[x][y]; 12 | 13 | // move values from right to top 14 | mat[x][y] = mat[y][N - 1 - x]; 15 | 16 | // move values from bottom to right 17 | mat[y][N - 1 - x] = mat[N - 1 - x][N - 1 - y]; 18 | 19 | // move values from left to bottom 20 | mat[N - 1 - x][N - 1 - y] = mat[N - 1 - y][x]; 21 | 22 | // assign temp to left 23 | mat[N - 1 - y][x] = temp; 24 | } 25 | } 26 | } 27 | var matrix = [ 28 | [1, 0, 1], 29 | [0, 0, 1], 30 | [1, 1, 1] 31 | ]; 32 | rotateMatrix90Left(matrix); 33 | 34 | console.log(matrix); 35 | // matrix = [ 36 | // [1,1,1], 37 | // [0,0,1], 38 | // [1,0,1] 39 | //] -------------------------------------------------------------------------------- /Problems/MultiDimensionalArrays/spiralPrint.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function spiralPrint(M) { 3 | var topRow = 0, 4 | leftCol = 0, 5 | btmRow = M.length - 1, 6 | rightCol = M[0].length - 1; 7 | 8 | while (topRow < btmRow && leftCol < rightCol) { 9 | for (var col = 0; col <= rightCol; col++) { 10 | console.log(M[topRow][col]); 11 | } 12 | topRow++; 13 | for (var row = topRow; row <= btmRow; row++) { 14 | console.log(M[row][rightCol]); 15 | } 16 | rightCol--; 17 | if (topRow <= btmRow) { 18 | for (var col = rightCol; col > 0; col--) { 19 | console.log(M[btmRow][col]); 20 | } 21 | btmRow--; 22 | } 23 | if (leftCol <= rightCol) { 24 | for (var row = btmRow; row > topRow; row--) { 25 | console.log(M[row][leftCol]); 26 | } 27 | leftCol++; 28 | } 29 | } 30 | } 31 | var M = [ 32 | [1, 2, 3, 4, 5], 33 | [6, 7, 8, 9, 10], 34 | [11, 12, 13, 14, 15], 35 | [16, 17, 18, 19, 20] 36 | ]; 37 | spiralPrint(M); -------------------------------------------------------------------------------- /Problems/MultiDimensionalArrays/ticTacToeWinner.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function checkRow ( rowArr, letter ) { 3 | for ( var i=0; i < 3; i++) { 4 | if (rowArr[i]!=letter) { 5 | return false; 6 | } 7 | } 8 | return true; 9 | } 10 | 11 | function checkColumn ( gameBoardMatrix, columnIndex, letter ) { 12 | for ( var i=0; i < 3; i++) { 13 | if (gameBoardMatrix[i][columnIndex]!=letter) { 14 | return false; 15 | } 16 | } 17 | return true; 18 | } 19 | 20 | function ticTacToeWinner ( gameBoardMatrix, letter) { 21 | 22 | // Check rows 23 | var rowWin = checkRow(gameBoardMatrix[0], letter) 24 | || checkRow(gameBoardMatrix[1], letter) 25 | || checkRow(gameBoardMatrix[2], letter); 26 | 27 | var colWin = checkColumn(gameBoardMatrix, 0, letter) 28 | || checkColumn(gameBoardMatrix, 1, letter) 29 | || checkColumn(gameBoardMatrix, 2, letter); 30 | 31 | var diagonalWinLeftToRight = (gameBoardMatrix[0][0]==letter && gameBoardMatrix[1][1]==letter && gameBoardMatrix[2][2]==letter); 32 | var diagonalWinRightToLeft = (gameBoardMatrix[0][2]==letter && gameBoardMatrix[1][1]==letter && gameBoardMatrix[2][0]==letter); 33 | 34 | return rowWin || colWin || diagonalWinLeftToRight || diagonalWinRightToLeft; 35 | } 36 | 37 | 38 | var board = [['O','-','X'],['-','O','-'],['-','X','O']]; 39 | ticTacToeWinner(board, 'X'); // false 40 | ticTacToeWinner(board, 'O'); // true -------------------------------------------------------------------------------- /Problems/Numbers/allPrimesLessThanN.js: -------------------------------------------------------------------------------- 1 | function allPrimesLessThanN(n) { 2 | for (var i = 0; i < n; i++) { 3 | if (isPrime(i)) { 4 | console.log(i); 5 | } 6 | } 7 | } 8 | 9 | function isPrime(n) { 10 | if (n <= 1) return false; 11 | if (n <= 3) return true; 12 | 13 | // This is checked so that we can skip 14 | // middle five numbers in below loop 15 | if (n % 2 == 0 || n % 3 == 0) return false; 16 | 17 | for (var i = 5; i * i <= n; i = i + 6) { 18 | if (n % i == 0 || n % (i + 2) == 0) { 19 | return false; 20 | } 21 | } 22 | 23 | return true; 24 | } 25 | 26 | allPrimesLessThanN(15); // prints 2, 3, 5, 7, 11, 13 -------------------------------------------------------------------------------- /Problems/Numbers/arrayNUglyNumbers.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function maxDivide(number, divisor) { 3 | while (number % divisor == 0) { 4 | number /= divisor; 5 | } 6 | return number; 7 | } 8 | 9 | function isUgly(number) { 10 | number = maxDivide(number, 2); 11 | number = maxDivide(number, 3); 12 | number = maxDivide(number, 5); 13 | return number === 1; 14 | } 15 | 16 | // Main 17 | function arrayNUglyNumbers(n) { 18 | var counter = 0, 19 | currentNumber = 1, 20 | uglyNumbers = []; 21 | 22 | while (counter != n) { 23 | 24 | if (isUgly(currentNumber)) { 25 | counter++; 26 | uglyNumbers.push(currentNumber); 27 | } 28 | 29 | currentNumber++; 30 | } 31 | 32 | return uglyNumbers; 33 | } 34 | 35 | console.log(arrayNUglyNumbers(11)); // [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15] -------------------------------------------------------------------------------- /Problems/Numbers/isPalindrome.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function isPalindrome(x) { 3 | if (x < 0) return false; 4 | var p = x, 5 | q = 0; 6 | while (p >= 10) { 7 | q *= 10; 8 | q += p % 10; 9 | p /= 10; 10 | } 11 | return q == x / 10 && p == x % 10; 12 | }; -------------------------------------------------------------------------------- /Problems/Numbers/modularExponentiation.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function modularExponentiationNaive(base, exponent, modulus) { 3 | return Math.pow(base, exponent) % modulus; 4 | } 5 | 6 | function modularExponentiation(base, exponent, modulus) { 7 | if (modulus == 1) return 0; 8 | 9 | var value = 1; 10 | 11 | for (var i = 0; i < exponent; i++) { 12 | value = (value * base) % modulus; 13 | } 14 | return value; 15 | } -------------------------------------------------------------------------------- /Problems/Recursion/base10ToBinary.js: -------------------------------------------------------------------------------- 1 | function base10ToString(n) { 2 | var binaryString = ""; 3 | 4 | function base10ToStringHelper(n) { 5 | if (n < 2) { 6 | binaryString += n; 7 | return; 8 | } else { 9 | base10ToStringHelper(Math.floor(n / 2)); 10 | base10ToStringHelper(n % 2); 11 | } 12 | } 13 | base10ToStringHelper(n); 14 | 15 | return binaryString; 16 | } 17 | 18 | console.log(base10ToString(232)); // 11101000 -------------------------------------------------------------------------------- /Problems/Recursion/flattenDictionary.js: -------------------------------------------------------------------------------- 1 | function flattenDictionary(dictionary) { 2 | var flattenedDictionary = {}; 3 | 4 | function flattenDitionaryHelper(dictionary, propName) { 5 | if (typeof dictionary != 'object') { 6 | flattenedDictionary[propName] = dictionary; 7 | return; 8 | } 9 | for (var prop in dictionary) { 10 | if (propName == '') { 11 | flattenDitionaryHelper(dictionary[prop], propName + prop); 12 | } else { 13 | flattenDitionaryHelper(dictionary[prop], propName + '.' + prop); 14 | } 15 | } 16 | } 17 | 18 | flattenDitionaryHelper(dictionary, ''); 19 | return flattenedDictionary; 20 | } 21 | 22 | var dictionary = { 23 | 'Key1': '1', 24 | 'Key2': { 25 | 'a': '2', 26 | 'b': '3', 27 | 'c': { 28 | 'd': '3', 29 | 'e': '1' 30 | } 31 | } 32 | } 33 | 34 | var dictionary2 = { 35 | 'Key1': '1', 36 | 'Wow': '1', 37 | 'I': { 38 | 'love': { 39 | 'coding': Infinity 40 | } 41 | } 42 | } 43 | 44 | console.log(flattenDictionary(dictionary)); // {Key1: "1", Key2.a: "2", Key2.b: "3", Key2.c.d: "3", Key2.c.e: "1"} 45 | console.log(flattenDictionary(dictionary2)); // {Key1: "1", Wow: "1", I.love.coding: Infinity} -------------------------------------------------------------------------------- /Problems/Recursion/isPalindromeRecursive.js: -------------------------------------------------------------------------------- 1 | function isPalindromeRecursive(word) { 2 | return isPalindromeHelper(word, 0, word.length - 1); 3 | } 4 | 5 | function isPalindromeHelper(word, beginPos, endPos) { 6 | if (beginPos >= endPos) { 7 | return true; 8 | } 9 | if (word.charAt(beginPos) != word.charAt(endPos)) { 10 | return false; 11 | } else { 12 | return isPalindromeHelper(word, beginPos + 1, endPos - 1); 13 | } 14 | } 15 | 16 | console.log(isPalindromeRecursive('hi')); // false 17 | console.log(isPalindromeRecursive('iii')); // true 18 | console.log(isPalindromeRecursive('ii')); // true 19 | console.log(isPalindromeRecursive('aibohphobia')); // true 20 | console.log(isPalindromeRecursive('racecar')); -------------------------------------------------------------------------------- /Problems/Recursion/permuteArray.js: -------------------------------------------------------------------------------- 1 | function swap(strArr, index1, index2) { 2 | var temp = strArr[index1]; 3 | strArr[index1] = strArr[index2]; 4 | strArr[index2] = temp; 5 | } 6 | 7 | function permute(strArr, begin, end) { 8 | if (begin == end) { 9 | console.log(strArr); 10 | } else { 11 | for (var i = begin; i < end + 1; i++) { 12 | swap(strArr, begin, i); 13 | permute(strArr, begin + 1, end); 14 | swap(strArr, begin, i); 15 | } 16 | } 17 | } 18 | 19 | function permuteArray(strArr) { 20 | permute(strArr, 0, strArr.length - 1); 21 | } 22 | 23 | permuteArray(["A", "C", "D"]); 24 | // ["A", "C", "D"] 25 | // ["A", "D", "C"] 26 | // ["C", "A", "D"] 27 | // ["C", "D", "A"] 28 | // ["D", "C", "A"] 29 | // ["D", "A", "C"] -------------------------------------------------------------------------------- /Problems/SearchSort/arraySort.js: -------------------------------------------------------------------------------- 1 | // Main 2 | var mythical = ['dragon', 'slayer', 'magic', 'wizard of oz', 'ned stark']; 3 | 4 | function sortComparator(a, b) { 5 | return a.length - b.length; 6 | } 7 | mythical.sort(sortComparator); 8 | // ["magic", "dragon", "slayer", "ned stark", "wizard of of"] 9 | 10 | var mythical = ['dragon', 'slayer', 'magic', 'wizard of oz', 'ned tark']; 11 | 12 | function sortComparator(a, b) { 13 | return a.indexOf("a") - b.indexOf("a"); 14 | } 15 | 16 | mythical.sort(sortComparator); 17 | // ["magic", "dragon", "slayer", "wizard of oz", "ned stark"] 18 | 19 | var mythical = [{ 20 | prop1: '', 21 | prop2: '' 22 | }, { 23 | prop1: '', 24 | prop2: '', 25 | prop3: '' 26 | }, { 27 | prop1: '', 28 | prop2: '' 29 | }]; 30 | 31 | function sortComparator(a, b) { 32 | return Object.keys(a).length - Object.keys(b).length; 33 | } 34 | 35 | mythical.sort(sortComparator); // [{prop1:'', prop2:''},{prop1:'', prop2:''},{prop1:'', prop2:'', prop3:''}] -------------------------------------------------------------------------------- /Problems/SearchSort/pigeonholeSort.js: -------------------------------------------------------------------------------- 1 | function pigeonholeSort(arr) { 2 | let max = Math.max.apply(Math, arr), 3 | min = Math.min.apply(Math, arr), 4 | holes = new Array(arr.length); 5 | 6 | for (let elm of arr) { 7 | if (holes[elm-min] == undefined) { 8 | holes[elm-min] = 0; 9 | } 10 | holes[elm-min] += 1; 11 | } 12 | 13 | let index = 0; 14 | for (let count=0; count<=max; count++) { 15 | while (holes[count] > 0) { 16 | holes[count] -= 1; 17 | arr[index] = count + min; 18 | index += 1; 19 | } 20 | } 21 | return arr; 22 | } 23 | let myArray = [5,3,8,11]; 24 | console.log(pigeonholeSort(myArray)); -------------------------------------------------------------------------------- /Problems/SearchSort/wordCount.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function wordCount(sentence) { 3 | // period with nothing so it doesn't count as word 4 | var wordsArray = sentence.replace(/[.]/g, "").split(" "), 5 | occurenceList = {}, 6 | answerList = {}, 7 | arrayTemp = []; 8 | 9 | for (var i = 0, wordsLength = wordsArray.length; i < wordsLength; i++) { 10 | var currentWord = wordsArray[i]; 11 | if (!occurenceList[currentWord]) { // doesn't exist, set as 1st occurrence 12 | occurenceList[currentWord] = 1; 13 | } else { 14 | occurenceList[currentWord]++; // add occurrences 15 | } 16 | } 17 | 18 | // push the value and key as fixed array 19 | for (var prop in occurenceList) { 20 | arrayTemp.push([occurenceList[prop], prop]); 21 | } 22 | 23 | function sortcomp(a, b) { 24 | return b[0] - a[0]; // compare the first element of the array 25 | } 26 | 27 | arrayTemp.sort(sortcomp); //sort 28 | 29 | for (var i = 0, arrlength = arrayTemp.length; i < arrlength; i++) { 30 | var current = arrayTemp[i]; 31 | answerList[current[1]] = current[0]; // key value pairs 32 | } 33 | return answerList; 34 | } 35 | console.log(wordCount("practice makes perfect. get perfect by practice. just practice")); // practice: 3, perfect: 2, makes: 1, get: 1, by: 1 } -------------------------------------------------------------------------------- /Problems/StacksQueues/CashierQueue.js: -------------------------------------------------------------------------------- 1 | // Main 2 | // Class for customer 3 | function Customer(name, order) { 4 | this.name = name; 5 | this.order = order; 6 | } 7 | 8 | // Class for cashier 9 | function Cashier() { 10 | this.customers = []; 11 | } 12 | 13 | Cashier.prototype.addOrder = function(customer) { 14 | this.customers.push(customer); 15 | } 16 | 17 | Cashier.prototype.deliverOrder = function() { 18 | var finishedCustomer = this.customers.shift(); 19 | 20 | console.log(finishedCustomer.name + ", your " + finishedCustomer.order + " is ready!"); 21 | } 22 | 23 | var cashier = new Cashier(); 24 | var customer1 = new Customer('Jim', "Fries"); 25 | var customer2 = new Customer('Sammie', "Burger"); 26 | var customer3 = new Customer('Peter', "Drink"); 27 | 28 | cashier.addOrder(customer1); 29 | cashier.addOrder(customer2); 30 | cashier.addOrder(customer3); 31 | 32 | cashier.deliverOrder(); // Jim, your Fries is ready! 33 | cashier.deliverOrder(); // Sammie, your Burger is ready! 34 | cashier.deliverOrder(); // Peter, your Drink is ready! -------------------------------------------------------------------------------- /Problems/StacksQueues/QueueStack.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | // Constructor 3 | function Queue(array) { 4 | this.array = []; 5 | if (array) this.array = array; 6 | } 7 | 8 | // Helpers 9 | Queue.prototype.getBuffer = function() { 10 | return this.array.slice(); 11 | } 12 | 13 | Queue.prototype.isEmpty = function() { 14 | return this.array.length == 0; 15 | } 16 | 17 | Queue.prototype.peek = function() { 18 | return this.array[0]; 19 | } 20 | 21 | // Insertion: 22 | // Time Complexity: O(1) 23 | // Space Complexity: O(1) 24 | Queue.prototype.enqueue = function(value) { 25 | return this.array.push(value); 26 | } 27 | 28 | // Deletion: 29 | // Time Complexity: O(1) 30 | // Space Complexity: O(1) 31 | Queue.prototype.dequeue = function() { 32 | return this.array.shift(); 33 | }; 34 | 35 | // Access: 36 | // Time Complexity: O(n) 37 | // Space Complexity: O(n) 38 | Queue.prototype.access = function(n) { 39 | var bufferArray = this.getBuffer(); 40 | if (n <= 0) throw 'error' 41 | 42 | var bufferStack = new Queue(bufferArray); 43 | 44 | while (--n !== 0) { 45 | bufferStack.dequeue(); 46 | } 47 | return bufferStack.dequeue(); 48 | } 49 | 50 | // Search: 51 | // Time Complexity: O(n) 52 | // Space Complexity: O(n) 53 | Queue.prototype.search = function(element) { 54 | var bufferArray = this.getBuffer(); 55 | var bufferQueue = new Queue(bufferArray); 56 | 57 | while (!bufferQueue.isEmpty()) { 58 | if (bufferQueue.dequeue() == element) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | // Main 66 | function QueueStack() { 67 | this.inbox = new Queue(); // first stack 68 | } 69 | 70 | QueueStack.prototype.push = function(val) { 71 | this.inbox.enqueue(val); 72 | }; 73 | 74 | QueueStack.prototype.pop = function() { 75 | var size = this.inbox.array.length - 1; 76 | var counter = 0; 77 | var bufferQueue = new Queue(); 78 | 79 | while (++counter <= size) { 80 | bufferQueue.enqueue(this.inbox.dequeue()); 81 | } 82 | var popped = this.inbox.dequeue(); 83 | this.inbox = bufferQueue; 84 | return popped 85 | }; 86 | 87 | var stack = new QueueStack(); 88 | 89 | stack.push(1); 90 | stack.push(2); 91 | stack.push(3); 92 | stack.push(4); 93 | stack.push(5); 94 | 95 | console.log(stack.pop()); // 5 96 | console.log(stack.pop()); // 4 97 | console.log(stack.pop()); // 3 98 | console.log(stack.pop()); // 2 99 | console.log(stack.pop()); // 1 -------------------------------------------------------------------------------- /Problems/StacksQueues/SortableStack.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | // Constructor 3 | function Stack(array) { 4 | this.array = []; 5 | if (array) this.array = array; 6 | } 7 | 8 | // Helpers 9 | Stack.prototype.getBuffer = function() { 10 | return this.array.slice(); 11 | } 12 | 13 | Stack.prototype.isEmpty = function() { 14 | return this.array.length == 0; 15 | } 16 | 17 | Stack.prototype.peek = function() { 18 | return this.array[this.array.length - 1]; 19 | } 20 | 21 | // Insertion: 22 | // Time Complexity: O(1) 23 | // Space Complexity: O(1) 24 | Stack.prototype.push = function(value) { 25 | this.array.push(value); 26 | } 27 | 28 | // Deletion: 29 | // Time Complexity: O(1) 30 | // Space Complexity: O(1) 31 | Stack.prototype.pop = function() { 32 | return this.array.pop(); 33 | }; 34 | 35 | // Main 36 | function SortableStack(size) { 37 | this.size = size; 38 | this.mainStack = new Stack(); 39 | this.sortedStack = new Stack(); 40 | } 41 | 42 | SortableStack.prototype.sortStackDescending = function() { 43 | while (!this.mainStack.isEmpty()) { 44 | var temp = this.mainStack.pop(); 45 | while (!this.sortedStack.isEmpty() && this.sortedStack.peek() < temp) { 46 | this.mainStack.push(this.sortedStack.pop()); 47 | } 48 | this.sortedStack.push(temp); 49 | } 50 | } 51 | 52 | SortableStack.prototype.sortStackAscending = function() { 53 | while (!this.mainStack.isEmpty()) { 54 | var temp = this.mainStack.pop(); 55 | while (!this.sortedStack.isEmpty() && this.sortedStack.peek() > temp) { 56 | this.mainStack.push(this.sortedStack.pop()); 57 | } 58 | this.sortedStack.push(temp); 59 | } 60 | } 61 | 62 | var ss = new SortableStack(10); 63 | 64 | // let's initialize it with some random ints 65 | for (var i = 0; i < ss.size; i++) { 66 | ss.mainStack.push(Math.floor(Math.random() * 11)); 67 | } 68 | 69 | console.log(ss); 70 | ss.sortStackDescending(); 71 | console.log(ss); -------------------------------------------------------------------------------- /Problems/StacksQueues/StackQueue.js: -------------------------------------------------------------------------------- 1 | // Constructor 2 | function Stack(array) { 3 | this.array = []; 4 | if (array) this.array = array; 5 | } 6 | 7 | // Helpers 8 | Stack.prototype.getBuffer = function() { 9 | return this.array.slice(); 10 | } 11 | 12 | Stack.prototype.isEmpty = function() { 13 | return this.array.length == 0; 14 | } 15 | 16 | Stack.prototype.peek = function() { 17 | return this.array[this.array.length - 1]; 18 | } 19 | 20 | // Insertion: 21 | // Time Complexity: O(1) 22 | // Space Complexity: O(1) 23 | Stack.prototype.push = function(value) { 24 | this.array.push(value); 25 | } 26 | 27 | // Deletion: 28 | // Time Complexity: O(1) 29 | // Space Complexity: O(1) 30 | Stack.prototype.pop = function() { 31 | return this.array.pop(); 32 | }; 33 | 34 | // Access: 35 | // Time Complexity: O(n) 36 | // Space Complexity: O(n) 37 | Stack.prototype.access = function(n) { 38 | var bufferArray = this.getBuffer(); 39 | if (n <= 0) throw 'error' 40 | 41 | var bufferStack = new Stack(bufferArray); 42 | 43 | while (--n !== 0) { 44 | bufferStack.pop(); 45 | } 46 | return bufferStack.pop(); 47 | }; 48 | 49 | // Search: 50 | // Time Complexity: O(n) 51 | // Space Complexity: O(n) 52 | Stack.prototype.search = function(element) { 53 | var bufferArray = this.getBuffer(); 54 | var bufferStack = new Stack(bufferArray); 55 | 56 | while (!bufferStack.isEmpty()) { 57 | if (bufferStack.pop() == element) { 58 | return true; 59 | } 60 | } 61 | 62 | return false; 63 | }; 64 | 65 | // Main 66 | function StackQueue() { 67 | this.inbox = new Stack(); // first stack 68 | this.outbox = new Stack(); 69 | } 70 | 71 | StackQueue.prototype.enqueue = function(val) { 72 | this.inbox.push(val); 73 | }; 74 | 75 | StackQueue.prototype.dequeue = function() { 76 | if (this.outbox.isEmpty()) { 77 | while (!this.inbox.isEmpty()) { 78 | this.outbox.push(this.inbox.pop()); 79 | } 80 | } 81 | return this.outbox.pop(); 82 | 83 | }; 84 | 85 | var queue = new StackQueue(); 86 | 87 | queue.enqueue(1); 88 | queue.enqueue(2); 89 | queue.enqueue(3); 90 | queue.enqueue(4); 91 | queue.enqueue(5); 92 | 93 | console.log(queue.dequeue()); // 1 94 | console.log(queue.dequeue()); // 2 95 | console.log(queue.dequeue()); // 3 96 | console.log(queue.dequeue()); // 4 97 | console.log(queue.dequeue()); // 5 -------------------------------------------------------------------------------- /Problems/StacksQueues/isParenthesisValid.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function isParenthesisValid(validationString) { 3 | var stack = []; 4 | for (var pos = 0; pos < validationString.length; pos++) { 5 | var currentChar = validationString.charAt(pos); 6 | if (currentChar == "(") { 7 | stack.push(currentChar); 8 | } else if (currentChar == ")") { 9 | 10 | if (stack.length == 0){ 11 | return false; 12 | } 13 | 14 | stack.pop(); 15 | } 16 | } 17 | return stack.length == 0; 18 | } 19 | 20 | console.log(isParenthesisValid("))")); // false 21 | console.log(isParenthesisValid(")")); // false 22 | console.log(isParenthesisValid("((()")); // false 23 | console.log(isParenthesisValid("((((")); // false 24 | console.log(isParenthesisValid("()()")); // true 25 | console.log(isParenthesisValid("()")); // true -------------------------------------------------------------------------------- /Problems/Strings/KMP.js: -------------------------------------------------------------------------------- 1 | function preProcessPattern(ptrn) { 2 | var i = 0, j = -1; 3 | var ptrnLen = ptrn.length; 4 | var b = new Array(ptrnLen + 1); 5 | 6 | b[i] = j; 7 | while (i < ptrnLen) { 8 | while (j >= 0 && ptrn[i] != ptrn[j]) { 9 | // if there is mismatch consider the next widest border 10 | // The borders to be examined are obtained in decreasing order from 11 | // the values b[i], b[b[i]] etc. 12 | j = b[j]; 13 | } 14 | i++; 15 | j++; 16 | b[i] = j; 17 | } 18 | return b; 19 | } 20 | 21 | 22 | function searchSubString(text, ptrn) { 23 | var i = 0, j = 0; 24 | // pattern and text lengths 25 | var ptrnLen = ptrn.length, 26 | txtLen = text.length; 27 | 28 | // initialize new array and preprocess the pattern 29 | var b = preProcessPattern(ptrn); 30 | 31 | while (i < txtLen) { 32 | while (j >= 0 && text[i] != ptrn[j]) { 33 | j = b[j]; 34 | } 35 | i++; 36 | j++; 37 | 38 | // a match is found 39 | if (j == ptrnLen) { 40 | return i - ptrnLen 41 | j = b[j]; 42 | } 43 | } 44 | } 45 | 46 | console.log(searchSubString('mississippi', 'iss')); // 4 -------------------------------------------------------------------------------- /Problems/Strings/compressString.js: -------------------------------------------------------------------------------- 1 | function compressString(longString) { 2 | var counter = 1, 3 | answer = '', 4 | last = longString.charAt(0); 5 | 6 | for (var i = 1; i < longString.length; i++) { 7 | var current = longString.charAt(i); 8 | 9 | if (last == current) { 10 | counter++; 11 | } else { 12 | answer += last + counter.toString(); 13 | counter = 1; 14 | } 15 | 16 | last = current; 17 | 18 | if (i == longString.length - 1) { 19 | answer += last + counter.toString(); 20 | } 21 | } 22 | if (answer.length > longString.length) 23 | return longString; 24 | return answer; 25 | } 26 | 27 | console.log(compressString('AAABCCDDDD')); -------------------------------------------------------------------------------- /Problems/Strings/convertToStringBaseX.js: -------------------------------------------------------------------------------- 1 | function convertToStringBaseX(num, x) { 2 | var abs = Math.abs(num), 3 | answer = ''; 4 | 5 | while (abs) { 6 | answer = (abs % x) + answer; 7 | abs = Math.floor(abs / x); 8 | } 9 | 10 | if (num < 0) { 11 | answer = '-' + answer; 12 | } 13 | 14 | return answer; 15 | } 16 | 17 | console.log(convertToStringBaseX(100, 7)); // 202 -------------------------------------------------------------------------------- /Problems/Strings/hashCode.js: -------------------------------------------------------------------------------- 1 | // Main 2 | String.prototype.hashCode = function() { 3 | var hash = 0, i, chr; 4 | if (this.length === 0) return hash; 5 | for (i = 0; i < this.length; i++) { 6 | chr = this.charCodeAt(i); 7 | hash = ((hash << 5) - hash) + chr; 8 | hash |= 0; // Convert to 32bit integer 9 | } 10 | return hash; 11 | }; -------------------------------------------------------------------------------- /Problems/Strings/indexOf.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function indexOf(str, subStr, startIndex) { 3 | var idx = 0, 4 | counter = 0; 5 | 6 | // if the optional startIndex was passed, set it to that. 7 | var i = startIndex | 0; 8 | 9 | for (; i < str.length; i++) { 10 | 11 | if (str[i] == subStr[counter]) { 12 | counter++; 13 | } else { 14 | counter = 0; 15 | } 16 | 17 | // Check starting point or a match 18 | if (counter == 0) { 19 | idx = i + 1; 20 | } else if (counter == subStr.length) { 21 | return idx; 22 | } 23 | } 24 | 25 | // Nothing found 26 | return -1; 27 | } 28 | 29 | console.log(indexOf('hello', 'll')); // prints '2' 30 | console.log(indexOf('hello', 'h')); // prints '0' 31 | console.log(indexOf('hello', 'll', 3)); // prints '-1' -------------------------------------------------------------------------------- /Problems/Strings/isAnagram.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function isAnagram(str1, str2) { 3 | return str1.split("").sort().join("") === str2.split("").sort().join(""); 4 | } 5 | 6 | function isAnagramBetter(str1, str2) { 7 | var hash1 = {}, 8 | hash2 = {}; 9 | if (str1.length != str2.length) return false; 10 | 11 | for (var i = 0, str1Length = str1.length; i < str1Length; i++) { 12 | if (hash1[str1.charAt(i)]) 13 | hash1[str1.charAt(i)]++; 14 | else 15 | hash1[str1.charAt(i)] = 1; 16 | } 17 | 18 | for (var i = 0, str2Length = str2.length; i < str2Length; i++) { 19 | if (hash2[str2.charAt(i)]) 20 | hash2[str2.charAt(i)]++; 21 | else 22 | hash2[str2.charAt(i)] = 1; 23 | } 24 | 25 | for (var prop in hash1) { 26 | if (!hash2[prop] || hash2[prop] !== hash1[prop]) 27 | return false; 28 | } 29 | return true; 30 | } -------------------------------------------------------------------------------- /Problems/Strings/isIsomorphic.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function isIsomorphic(s, t) { 3 | var sCharArray = [], 4 | tCharArray = []; // max size 256 this is for use of .charCodeAt 5 | 6 | for (var i = 0, stLength = s.length; i < stLength; i++) { 7 | var sCurrent = s.charCodeAt(i), 8 | tCurrent = t.charCodeAt(i); 9 | 10 | if (sCharArray[sCurrent] == null) 11 | sCharArray[sCurrent] = 0; 12 | if (tCharArray[tCurrent] == null) 13 | tCharArray[tCurrent] = 0; 14 | 15 | if (sCharArray[sCurrent] == 0 && tCharArray[tCurrent] == 0) { 16 | sCharArray[sCurrent] = tCurrent; 17 | tCharArray[tCurrent] = sCurrent; 18 | } else if (tCharArray[tCurrent] != sCurrent || sCharArray[sCurrent] != tCurrent) { 19 | return false; 20 | } 21 | } 22 | return true; 23 | }; 24 | 25 | var testSet1 = ["egg", "add"], 26 | testSet2 = ["foo", "bar"], 27 | testSet3 = ["paper", "title"]; 28 | 29 | console.log(isIsomorphic(testSet1[0], testSet1[1])); // true 30 | console.log(isIsomorphic(testSet2[0], testSet2[1])); // false 31 | console.log(isIsomorphic(testSet3[0], testSet3[1])); // true -------------------------------------------------------------------------------- /Problems/Strings/longestCommonSequenceLength.js: -------------------------------------------------------------------------------- 1 | function lcs(A, B, indexA, indexB) { 2 | if (indexA <= 0 || indexB <= 0) { 3 | return 0; 4 | } else if (A[indexA-1] == B[indexB-1]) { 5 | return 1 + lcs(A, B, indexA-1, indexB-1); 6 | } else { 7 | return Math.max(lcs(A, B, indexA-1, indexB), lcs(A, B, indexA, indexB-1)); 8 | } 9 | } 10 | console.log(lcs("AYXT", "AYZXT", 4, 5)); // 4 ('AYXT') -------------------------------------------------------------------------------- /Problems/Strings/longestCommonSequenceLengthDP.js: -------------------------------------------------------------------------------- 1 | function lcsDP(A, B) { 2 | var matrix = []; 3 | 4 | for (var i = 0; i < A.length + 1; i++) { 5 | matrix.push(new Array(B.length + 1)); 6 | } 7 | 8 | for (var i = 0; i < A.length + 1; i++) { 9 | 10 | for (var j = 0; j < B.length + 1; j++) { 11 | if (i == 0 || j == 0) { 12 | matrix[i][j] = 0; 13 | } else if (A[i - 1] == B[j - 1]) { 14 | matrix[i][j] = matrix[i - 1][j - 1] + 1; 15 | } else { 16 | matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]); 17 | } 18 | } 19 | 20 | } 21 | return matrix[A.length][B.length]; 22 | } 23 | console.log(lcsDP("AYXT", "AYZXT")); // 4 -------------------------------------------------------------------------------- /Problems/Strings/longestCommonSequenceString.js: -------------------------------------------------------------------------------- 1 | function lcs(A, B, indexA, indexB) { 2 | if (indexA <= 0 || indexB <= 0) { 3 | return ''; 4 | } else if (A[indexA - 1] == B[indexB - 1]) { 5 | return lcs(A, B, indexA - 1, indexB - 1) + A[indexA - 1]; 6 | } else { 7 | var temp1 = lcs(A, B, indexA - 1, indexB), 8 | temp2 = lcs(A, B, indexA, indexB - 1); 9 | 10 | if (temp1.length == temp2.length) { 11 | return temp1; 12 | } else if (temp1.length > temp2.length) { 13 | return temp1; 14 | } else { 15 | return temp2; 16 | } 17 | } 18 | } 19 | console.log(lcs("AYXT", "AYZXT", 4, 5)); // 'AYXT' -------------------------------------------------------------------------------- /Problems/Strings/longestCommonSequenceStringDP.js: -------------------------------------------------------------------------------- 1 | function lcsDP(A, B) { 2 | var matrix = []; 3 | 4 | for (var i = 0; i < A.length + 1; i++) { 5 | matrix.push(new Array(B.length + 1)); 6 | } 7 | 8 | for (var i = 0; i < A.length + 1; i++) { 9 | 10 | for (var j = 0; j < B.length + 1; j++) { 11 | if (i == 0 || j == 0) { 12 | matrix[i][j] = ''; 13 | } else if (A[i - 1] == B[j - 1]) { 14 | matrix[i][j] = matrix[i - 1][j - 1] + A[i - 1]; 15 | } else { 16 | if (matrix[i - 1][j].length == matrix[i][j -1]) { 17 | matrix[i][j] = matrix[i - 1][j]; 18 | } else if (matrix[i - 1][j].length > matrix[i][j -1]) { 19 | matrix[i][j] = matrix[i - 1][j]; 20 | } else { 21 | matrix[i][j] == matrix[i][j -1]; 22 | } 23 | 24 | } 25 | } 26 | 27 | } 28 | return matrix[A.length][B.length]; 29 | } 30 | console.log(lcsDP("AYXT", "AYZXT")); // 4 -------------------------------------------------------------------------------- /Problems/Strings/maxSubArray.js: -------------------------------------------------------------------------------- 1 | function maxSubArray(nums) { 2 | let maxCurrent = nums[0], 3 | maxGlobal = nums[0]; 4 | 5 | for (let i=1; i < nums.length; i++ ) { 6 | // now or sum of now and before 7 | maxCurrent = Math.max(nums[i], nums[i] + maxCurrent); 8 | maxGlobal = Math.max(maxGlobal, maxCurrent); 9 | } 10 | return maxGlobal; 11 | } 12 | 13 | console.log(maxSubArray([2,-3,2,1])); -------------------------------------------------------------------------------- /Problems/Strings/removeExtraSpaces.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function removeExtraSpaces(str) { 3 | var newString = "", 4 | lastChar = " "; 5 | 6 | for (var i = 0, strLength = str.length; i < strLength; i++) { 7 | 8 | var currentChar = str.charAt(i), 9 | currentAndLastIsSpace = lastChar == " " && currentChar == " ", 10 | nextCharIsSpace = (i < strLength - 1 && str.charAt(i + 1) == " " && currentChar == " "); 11 | 12 | if (!(currentAndLastIsSpace || nextCharIsSpace)) { 13 | newString += currentChar; 14 | } 15 | 16 | lastChar = currentChar; 17 | } 18 | return newString; 19 | } 20 | 21 | console.log(removeExtraSpaces(" hello. how are you doing? ")); // "hello.how are you doing?" -------------------------------------------------------------------------------- /Problems/Strings/reverseString.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function reverseString(str) { 3 | var reversed = ""; 4 | for (var i = str.length - 1; i >= 0; i--) { 5 | reversed += str.charAt(i); 6 | } 7 | return reversed; 8 | } -------------------------------------------------------------------------------- /Problems/Strings/reverseWords.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function reverseWords(str) { 3 | var temp = "", 4 | reversedSetence = ""; 5 | 6 | for (var i = 0; i < str.length; i++) { 7 | 8 | // only put the extra space if not the last word 9 | var spaceForWord = i === str.length - 1 ? "" : " "; 10 | 11 | // if space is encountered 12 | if (str.charAt(i) === " ") { 13 | // reverse and concat 14 | reversedSetence += reverseString(temp) + spaceForWord; 15 | // reset the temp 16 | temp = ""; 17 | } else { 18 | temp += str.charAt(i); 19 | } 20 | 21 | // reached the end of the input 22 | if (i === str.length - 1) { 23 | reversedSetence += reverseString(temp); 24 | } 25 | } 26 | 27 | return reversedSetence; 28 | } 29 | 30 | function reverseString(str) { 31 | var reversed = ""; 32 | for (var i = str.length - 1; i >= 0; i--) { 33 | reversed += str.charAt(i); 34 | } 35 | return reversed; 36 | } 37 | console.log(reverseWords("hello how are you doing")); -------------------------------------------------------------------------------- /Problems/Strings/wordsIsRotation.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function wordIsRotation(word1, word2) { 3 | if (!word1 || !word2 || word1.length != word2.length) { 4 | return false; 5 | } 6 | return (word1+word1).indexOf(word2) != -1; 7 | } 8 | 9 | console.log(wordIsRotation('foobarbaz', 'barbazfoo')); 10 | console.log(wordIsRotation('same', 'mesa')); -------------------------------------------------------------------------------- /Problems/Trees/binaryTreeToArray.js: -------------------------------------------------------------------------------- 1 | function binaryTreeToArray(root, size) { 2 | var array = new Array(size); // dynamic 3 | 4 | 5 | var queue = [[root, 0]]; 6 | 7 | while (queue.length) { 8 | var nodeTuple = queue.shift(), 9 | node = nodeTuple[0], 10 | nodeIndex = nodeTuple[1]; 11 | console.log(node); 12 | array[nodeIndex] = node.value; 13 | 14 | if (node.right) { 15 | queue.push( [node.right, (nodeIndex * 2 + 2)]); 16 | } 17 | 18 | if (node.left) { 19 | queue.push([node.left, (nodeIndex * 2 + 1)]); 20 | } 21 | 22 | } 23 | return array; 24 | } 25 | 26 | var node3 = { 27 | value: 1, 28 | left: { 29 | value: 0 30 | }, 31 | right: { 32 | value: 2, 33 | left: { 34 | value: 1.5 35 | }, 36 | right: { 37 | value: 3 38 | } 39 | } 40 | } 41 | 42 | console.log(binaryTreeToArray(node3, 5)); -------------------------------------------------------------------------------- /Problems/Trees/checkIfSubtree.js: -------------------------------------------------------------------------------- 1 | function isSameTree(root1, root2) { 2 | if (root1 == null && root2 == null) { 3 | return true; 4 | } 5 | if (root1 == null || root2 == null) { 6 | return false; 7 | } 8 | 9 | return root1.value == root2.value && isSameTree(root1.left, root2.left) && isSameTree(root1.right, root2.right) 10 | } 11 | 12 | function checkIfSubTree(root, subtree) { 13 | // Breath first search 14 | var queue = [], 15 | counter = 0; 16 | 17 | // sanity check for root 18 | if (!root) { 19 | return; 20 | } 21 | 22 | queue.push(root); 23 | 24 | while (queue.length) { 25 | var temp = queue.shift(); 26 | 27 | if (temp.data == subtree.data == isSameTree(temp, subtree)) { 28 | return true; 29 | } 30 | 31 | if (temp.left) { 32 | queue.push(temp.left); 33 | } 34 | if (temp.right) { 35 | queue.push(temp.right); 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | var node1 = { 42 | value: 5, 43 | left: { 44 | value: 3, 45 | left: { 46 | value: 1 47 | }, 48 | right: { 49 | value: 2 50 | } 51 | }, 52 | right: { 53 | value: 7 54 | } 55 | } 56 | 57 | var node2 = { 58 | value: 3, 59 | left: { 60 | value: 1 61 | }, 62 | right: { 63 | value: 2 64 | } 65 | } 66 | 67 | 68 | var node3 = { 69 | value: 3, 70 | left: { 71 | value: 1 72 | } 73 | } 74 | 75 | console.log(checkIfSubTree(node1, node2)); // true 76 | console.log(checkIfSubTree(node1, node3)); // false 77 | console.log(checkIfSubTree(node2, node3)); // false -------------------------------------------------------------------------------- /Problems/Trees/createBSTFromArray.js: -------------------------------------------------------------------------------- 1 | // Helpers 2 | function BSTNode(val) { 3 | this.val = val; 4 | this.left= null; 5 | this.right=null; 6 | } 7 | 8 | // Main 9 | function createBSTFromArray(arr) { 10 | // assumes that arr is sorted 11 | function createBSTFromArrayHelper(arr, left, right) { 12 | if (right < left) { 13 | return; 14 | } 15 | var mid = Math.floor((left+right)/2), 16 | node = new BSTNode(arr[mid]); 17 | node.left = createBSTFromArrayHelper(arr, left, mid-1); 18 | node.right= createBSTFromArrayHelper(arr, mid+1, right); 19 | return node; 20 | } 21 | return createBSTFromArrayHelper(arr,0,arr.length-1); 22 | } 23 | 24 | console.log(createBSTFromArray([1,2,3,4,5,6,7,8,9,10])); -------------------------------------------------------------------------------- /Problems/Trees/deepestLeft.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function deepestLeft(root) { 3 | var queue = [root]; 4 | 5 | while (queue.length) { 6 | root = queue.shift(); 7 | 8 | if (root.right) { 9 | queue.push(root.right); 10 | } 11 | 12 | if (root.left) { 13 | queue.push(root.left); 14 | } 15 | } 16 | return root.value; 17 | } 18 | 19 | 20 | var node1 = { 21 | value: 5, 22 | left: { 23 | value: 3, 24 | left: { 25 | value: -122 26 | }, 27 | right: { 28 | value: 2 29 | } 30 | }, 31 | right: { 32 | value: 7 33 | } 34 | } 35 | 36 | var node2 = { 37 | value: 3, 38 | left: { 39 | value: 1 40 | }, 41 | right: { 42 | value: 2 43 | } 44 | } 45 | 46 | var node3 = { 47 | value: 3, 48 | left: { 49 | value: 1 50 | } 51 | } 52 | 53 | console.log(deepestLeft(node1)); // -122 54 | console.log(deepestLeft(node2)); // 1 55 | console.log(deepestLeft(node3)); // 1 -------------------------------------------------------------------------------- /Problems/Trees/deepestRight.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function deepestRight(root) { 3 | var queue = [root]; 4 | 5 | while (queue.length) { 6 | root = queue.shift(); 7 | 8 | if (root.left) { 9 | queue.push(root.left); 10 | } 11 | 12 | if (root.right) { 13 | queue.push(root.right); 14 | } 15 | 16 | } 17 | return root.value; 18 | } 19 | 20 | 21 | var node1 = { 22 | value: 5, 23 | left: { 24 | value: 3, 25 | left: { 26 | value: -122 27 | }, 28 | right: { 29 | value: 2 30 | } 31 | }, 32 | right: { 33 | value: 7 34 | } 35 | } 36 | 37 | var node2 = { 38 | value: 3, 39 | left: { 40 | value: 1 41 | }, 42 | right: { 43 | value: 2 44 | } 45 | } 46 | 47 | var node3 = { 48 | value: 3, 49 | left: { 50 | value: 1 51 | } 52 | } 53 | 54 | console.log(deepestRight(node1)); // 2 55 | console.log(deepestRight(node2)); // 2 56 | console.log(deepestRight(node3)); // 1 -------------------------------------------------------------------------------- /Problems/Trees/findLowestCommonAncestor.js: -------------------------------------------------------------------------------- 1 | function findLowestCommonAncestor(root, value1, value2) { 2 | // helper function inside this scope 3 | function findLowestCommonAncestorHelper(root, value1, value2) { 4 | if (!root) 5 | return; 6 | if (Math.max(value1, value2) < root.value) 7 | return findLowestCommonAncestorHelper(root.left, value1, value2); 8 | if (Math.min(value1, value2) > root.value) 9 | return findLowestCommonAncestorHelper(root.right, value1, value2); 10 | return root.value 11 | } 12 | return findLowestCommonAncestorHelper(root, value1, value2); 13 | } 14 | 15 | var node1 = { 16 | value: 1, 17 | left: { 18 | value: 0 19 | }, 20 | right: { 21 | value: 2 22 | } 23 | } 24 | 25 | var node2 = { 26 | value: 1, 27 | left: { 28 | value: 0, 29 | left: { 30 | value: -1 31 | }, 32 | right: { 33 | value: 0.5 34 | } 35 | }, 36 | right: { 37 | value: 2 38 | } 39 | } 40 | 41 | var node3 = { 42 | value: 1, 43 | left: { 44 | value: 0 45 | }, 46 | right: { 47 | value: 2, 48 | left: { 49 | value: 1.5 50 | }, 51 | right: { 52 | value: 3 53 | } 54 | } 55 | } 56 | 57 | console.log(findLowestCommonAncestor(node1, 0, 2)); // 1 58 | console.log(findLowestCommonAncestor(node2, 0, 2)); // 1 59 | console.log(findLowestCommonAncestor(node1, 0.5, -1)); // 0 60 | console.log(findLowestCommonAncestor(node3, 0, 1.5)); // 1 61 | console.log(findLowestCommonAncestor(node3, 1.5, 3)); // 2 -------------------------------------------------------------------------------- /Problems/Trees/getHeight.js: -------------------------------------------------------------------------------- 1 | function getHeight(root) { 2 | 3 | // helper recursive function 4 | function getHeightHelper(root) { 5 | if (!root) return 0; 6 | return Math.max(getHeightHelper(root.left) + 1, getHeightHelper(root.right) + 1); 7 | } 8 | 9 | return getHeightHelper(root); 10 | } 11 | 12 | var node1 = { 13 | value: 1, 14 | left: { 15 | value: 0 16 | }, 17 | right: { 18 | value: 2 19 | } 20 | } 21 | 22 | var node2 = { 23 | value: 1, 24 | left: { 25 | value: 0, 26 | left: { 27 | value: -1 28 | }, 29 | right: { 30 | value: 0.5 31 | } 32 | }, 33 | right: { 34 | value: 2 35 | } 36 | } 37 | 38 | var node3 = { 39 | value: 1, 40 | left: { 41 | value: 0 42 | }, 43 | right: { 44 | value: 2, 45 | left: { 46 | value: 1.5 47 | }, 48 | right: { 49 | value: 3, 50 | left: { 51 | value: 3.25 52 | } 53 | } 54 | } 55 | } 56 | 57 | console.log(getHeight(node1)); // 2 58 | console.log(getHeight(node2)); // 3 59 | console.log(getHeight(node3)); // 4 -------------------------------------------------------------------------------- /Problems/Trees/hasPathSum.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function hasPathSum(root, sum) { 3 | if (!root) return false; 4 | if (!root.left && !root.right && sum - root.val == 0) return true; 5 | return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); 6 | }; 7 | 8 | var node1 = { 9 | val: 1, 10 | left: { 11 | val: 2, 12 | right: { 13 | val: 5 14 | } 15 | }, 16 | right: { 17 | val: 10, 18 | right: { 19 | val: 12 20 | } 21 | } 22 | }; 23 | // left's children path add up to 8: 1 + 2 + 5 24 | // right's children path add up to 23: 1 + 10 + 12 25 | console.log(hasPathSum(node1, 8)); // true 26 | console.log(hasPathSum(node1, 10)); // true 27 | console.log(hasPathSum(node1, 23)); // false; 28 | console.log(hasPathSum(node1, 13)); // false; -------------------------------------------------------------------------------- /Problems/Trees/invertTree.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function invertTree(root) { 3 | function invertTreeHelper(root) { 4 | if (!root) { 5 | return; 6 | } 7 | invertTreeHelper(root.left); 8 | invertTreeHelper(root.right); 9 | 10 | let temp = root.right; 11 | root.right = root.left; 12 | root.left = temp; 13 | return root; 14 | } 15 | return invertTreeHelper(root); 16 | } 17 | var sampleTree = {'val': 4, 'left': {'val': 3, 'left':{}, 'right':{}} ,'right': {'val': 5, 'left':{}, 'right':{}}}; 18 | console.log(invertTree(sampleTree)); -------------------------------------------------------------------------------- /Problems/Trees/isMirrorTrees.js: -------------------------------------------------------------------------------- 1 | function isMirrorTrees(tree1, tree2) { 2 | 3 | // Base case, both empty 4 | if (!tree1 && !tree2) { 5 | return true; 6 | } 7 | 8 | // One of them is empty, since only one is empty, not mirrored 9 | if (!tree1 || !tree2) { 10 | return false; 11 | } 12 | 13 | // Both non-empty, compare them recursively. 14 | // Pass left of one and right of the other 15 | 16 | var checkLeftwithRight = isMirrorTrees(tree1.left, tree2.right), 17 | checkRightwithLeft = isMirrorTrees(tree2.right, tree1.left); 18 | 19 | return tree1.data == tree2.data && checkLeftwithRight && checkRightwithLeft; 20 | } 21 | 22 | var node1 = { 23 | value: 3, 24 | left: { 25 | value: 1 26 | }, 27 | right: { 28 | value: 2 29 | } 30 | } 31 | 32 | var node2 = { 33 | value: 3, 34 | left: { 35 | value: 1 36 | }, 37 | right: { 38 | value: 2 39 | } 40 | } 41 | 42 | var node3 = { 43 | value: 3, 44 | left: { 45 | value: 1 46 | }, 47 | right: { 48 | value: 2, 49 | left: { 50 | value: 2.5 51 | } 52 | } 53 | } 54 | 55 | var node4 = { 56 | value: 3, 57 | left: { 58 | value: 1, 59 | right : { 60 | value: 2.5 61 | } 62 | }, 63 | right: { 64 | value: 2 65 | } 66 | } 67 | 68 | 69 | console.log(isMirrorTrees(node1, node2)); // true 70 | console.log(isMirrorTrees(node2, node3)); // false 71 | console.log(isMirrorTrees(node3, node4)); // true -------------------------------------------------------------------------------- /Problems/Trees/isSameTree.js: -------------------------------------------------------------------------------- 1 | function isSameTree(root1, root2) { 2 | if (root1 == null && root2 == null) { 3 | return true; 4 | } 5 | if (root1 == null || root2 == null) { 6 | return false; 7 | } 8 | 9 | return root1.value == root2.value && isSameTree(root1.left, root2.left) && isSameTree(root1.right, root2.right) 10 | } 11 | 12 | var node1 = { 13 | value: 3, 14 | left: { 15 | value: 1 16 | }, 17 | right: { 18 | value: 2 19 | } 20 | } 21 | 22 | var node2 = { 23 | value: 5, 24 | left: { 25 | value: 3 26 | }, 27 | right: { 28 | value: 7 29 | } 30 | } 31 | 32 | var node3 = { 33 | value: 3, 34 | left: { 35 | value: 1 36 | } 37 | } 38 | 39 | var node4 = { 40 | value: 3, 41 | right: { 42 | value: 2 43 | } 44 | } 45 | console.log(isSameTree(node1, node1)); // true 46 | console.log(isSameTree(node2, node2)); // true 47 | console.log(isSameTree(node1, node2)); // false 48 | console.log(isSameTree(node1, node3)); // false 49 | console.log(isSameTree(node1, node4)); // false -------------------------------------------------------------------------------- /Problems/Trees/isTreeUnival.js: -------------------------------------------------------------------------------- 1 | function isTreeUnival(root) { 2 | if (!root || !root.left && !root.right) { 3 | return true; 4 | } 5 | 6 | var checkChild = true; 7 | 8 | if (root.left || root.right) { 9 | if (root.left && root.right) { 10 | checkChild = root.value == root.left.value && root.value == root.right.value; 11 | } else if (root.left && !root.right) { 12 | checkChild = root.value == root.left.value 13 | } else { 14 | checkChild = root.value == root.right.value 15 | } 16 | } 17 | return checkChild && isTreeUnival(root.left) && isTreeUnival(root.right); 18 | } 19 | 20 | var node1 = { 21 | value: 2, 22 | left: { 23 | value: 2 24 | }, 25 | right: { 26 | value: 2 27 | } 28 | } 29 | 30 | var node2 = { 31 | value: 2, 32 | left: { 33 | value: 2 34 | }, 35 | right: { 36 | value: 2, 37 | left: { 38 | value: 2 39 | } 40 | } 41 | } 42 | 43 | var node3 = { 44 | value: 1, 45 | left: { 46 | value: 2 47 | }, 48 | right: { 49 | value: 2 50 | } 51 | } 52 | 53 | var node4 = { 54 | value: 2, 55 | left: { 56 | value: 2 57 | }, 58 | right: { 59 | value: 2, 60 | left: { 61 | value: 1 62 | } 63 | } 64 | } 65 | 66 | console.log(isTreeUnival(node1)); // true 67 | console.log(isTreeUnival(node2)); // true 68 | console.log(isTreeUnival(node3)); // false 69 | console.log(isTreeUnival(node4)); // false -------------------------------------------------------------------------------- /Problems/Trees/maxDepth.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function maxDepth(root, height) { 3 | if (root == null) return 0; 4 | var left = minDepth(root.left); 5 | var right = minDepth(root.right); 6 | return (left == 0 || right == 0) ? left + right + 1 : Math.max(left, right) + 1; 7 | }; -------------------------------------------------------------------------------- /Problems/Trees/minDepth.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function minDepth(root, height) { 3 | if (root == null) return 0; 4 | var left = minDepth(root.left); 5 | var right = minDepth(root.right); 6 | return (left == 0 || right == 0) ? left + right + 1 : Math.min(left, right) + 1; 7 | }; -------------------------------------------------------------------------------- /Problems/Trees/printKthLevels.js: -------------------------------------------------------------------------------- 1 | function getHeight(root) { 2 | // helper recursive function 3 | function getHeightHelper(root) { 4 | if (!root) return 0; 5 | return Math.max(getHeightHelper(root.left) + 1, getHeightHelper(root.right) + 1); 6 | } 7 | 8 | return getHeightHelper(root); 9 | } 10 | 11 | function printKthLevels(root, k) { 12 | var rootHeight = getHeight(root), 13 | arrayKth = [], 14 | queue = [] 15 | 16 | if (!root) return; 17 | 18 | // Breath first search for tree 19 | queue.push(root); 20 | 21 | while (queue.length) { 22 | var temp = queue.shift(); 23 | 24 | if (getHeight(temp) == rootHeight - k + 1) { 25 | // Kth level is height - k + 1 26 | arrayKth.push(temp.value); 27 | } 28 | if (temp.left) { 29 | queue.push(temp.left); 30 | } 31 | if (temp.right) { 32 | queue.push(temp.right); 33 | } 34 | } 35 | console.log(arrayKth); 36 | } 37 | 38 | 39 | var node1 = { 40 | value: 1, 41 | left: { 42 | value: 0 43 | }, 44 | right: { 45 | value: 2 46 | } 47 | } 48 | 49 | var node2 = { 50 | value: 1, 51 | left: { 52 | value: 0, 53 | left: { 54 | value: -1 55 | }, 56 | right: { 57 | value: 0.5 58 | } 59 | }, 60 | right: { 61 | value: 2 62 | } 63 | } 64 | 65 | var node3 = { 66 | value: 1, 67 | left: { 68 | value: 0 69 | }, 70 | right: { 71 | value: 2, 72 | left: { 73 | value: 1.5 74 | }, 75 | right: { 76 | value: 3, 77 | left: { 78 | value: 3.25 79 | } 80 | } 81 | } 82 | } 83 | 84 | printKthLevels(node1, 1); // 1 85 | printKthLevels(node1, 2); // [0,2] -------------------------------------------------------------------------------- /Problems/Trees/rightSideView.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function rightSideView(root) { 3 | if (!root) return []; 4 | var result = []; 5 | 6 | function helper(root, level) { 7 | if (!root) return; 8 | if (result.length < level) 9 | result.push(root.val); 10 | helper(root.right, level + 1); 11 | helper(root.left, level + 1); 12 | } 13 | helper(root, 1); 14 | return result; 15 | }; 16 | 17 | var node1 = { 18 | val: 1, 19 | left: { 20 | val: 2, 21 | right: { 22 | val: 5 23 | } 24 | }, 25 | right: { 26 | val: 10, 27 | right: { 28 | val: 12 29 | } 30 | } 31 | }; 32 | 33 | var node2 = { 34 | val: 1, 35 | right: { 36 | val: 2, 37 | right: { 38 | val: 5 39 | } 40 | }, 41 | left: { 42 | val: 10, 43 | right: { 44 | val: 12 45 | } 46 | } 47 | }; 48 | 49 | console.log(rightSideView(node1)); // [10, 2, 5] 50 | console.log(rightSideView(node2)); // [1, 2, 5] -------------------------------------------------------------------------------- /Problems/Trees/sumOfLeftLeaves.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function sumOfLeftLeaves(root, shouldAdd) { 3 | if (!root) return 0; 4 | 5 | if (!root.left && !root.right && shouldAdd) { 6 | return root.val; 7 | } 8 | 9 | var left = sumOfLeftLeaves(root.left, true); 10 | var right = sumOfLeftLeaves(root.right, false); 11 | 12 | return left + right; 13 | }; -------------------------------------------------------------------------------- /Problems/Trees/sumOfRightLeaves.js: -------------------------------------------------------------------------------- 1 | // Main 2 | function sumOfRightLeaves(root, shouldAdd) { 3 | if (!root) return 0; 4 | 5 | if (!root.left && !root.right && shouldAdd) { 6 | return root.val; 7 | } 8 | 9 | var left = sumOfRightLeaves(root.left, false); 10 | var right = sumOfRightLeaves(root.right, true); 11 | 12 | return left + right; 13 | }; -------------------------------------------------------------------------------- /Problems/Trees/upsideDownBinaryTree.js: -------------------------------------------------------------------------------- 1 | function upsideDownBinaryTree(root) { 2 | var current = root, 3 | prev = null, 4 | next = null, 5 | temp = null; 6 | 7 | while (current) { 8 | next = current.left; 9 | current.left = temp; 10 | temp = current.right; 11 | current.right = prev; 12 | prev = current; 13 | current = next; 14 | } 15 | return prev; 16 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsds 2 | Data Structures and Algorithms written in JavaScript 3 | 4 | Supplementary code for the book: [JavaScript Data Structures and Algorithms](https://leanpub.com/javascriptdatastructuresandalgorithms) 5 | 6 | This repository contains all the code used in the book as well as other supplementary code for helper functions. -------------------------------------------------------------------------------- /Strings/base62Encode.js: -------------------------------------------------------------------------------- 1 | var DICTIONARY = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split(''); 2 | 3 | function encodeId(num) { 4 | var base = DICTIONARY.length; 5 | var encoded = ''; 6 | 7 | if (num === 0) { 8 | return DICTIONARY[0]; 9 | } 10 | 11 | while (num > 0) { 12 | encoded += DICTIONARY[(num % base)]; 13 | num = Math.floor(num / base); 14 | } 15 | 16 | return reverseWord(encoded); 17 | } 18 | 19 | function reverseWord(str) { 20 | var reversed = ""; 21 | for (var i = str.length - 1; i >= 0; i--) { 22 | reversed += str.charAt(i); 23 | } 24 | return reversed; 25 | } 26 | 27 | function decodeId(id) { 28 | var base = DICTIONARY.length; 29 | var decoded = 0; 30 | 31 | for (var index = 0; index < id.split("").length; index++) { 32 | decoded = decoded * base + DICTIONARY.indexOf(id.charAt(index)); 33 | } 34 | 35 | return decoded; 36 | } 37 | 38 | console.log(encodeId(11231230)); // prints 'VhU2' 39 | console.log(decodeId('VhU2')); // prints '11231230' --------------------------------------------------------------------------------