├── src ├── leetCode │ ├── two_sum.js │ ├── remove_duplicates_array.js │ ├── max_depth_binary_tree.js │ ├── coin_change.java │ ├── min_deletion_size.js │ ├── minIncrement.js │ ├── linked_list_cycle.js │ ├── binary_tree_inorder.js │ ├── swap_array.js │ ├── reverse_string_ii.js │ ├── add_two_numbers.js │ ├── three_sum.js │ ├── lca_binary_tree.java │ ├── odd_even_linkedlist.js │ ├── first_bad_version.js │ ├── max_profit_DP.js │ ├── valid_parenthesis.js │ ├── shortest_completing_word.java │ ├── min_stack.js │ ├── chess_queen.js │ ├── remove_stones.js │ ├── shuffle_array.java │ ├── stack_using_queues.js │ ├── alien_dictionary.js │ ├── max_profit.js │ ├── largest_time_give_digits.js │ ├── number_of_islands.java │ ├── binary_subtract.js │ └── kitty_distance.js ├── classic │ ├── sorting │ │ ├── quick_sort.js │ │ ├── heap_sort2.js │ │ ├── insertion_sort.js │ │ ├── radix_sort.js │ │ ├── heap_sort.js │ │ └── merge_sort.js │ ├── permutations.js │ ├── linkedList │ │ └── linked_list.js │ ├── string │ │ ├── kmp.js │ │ └── rabin_karp.js │ ├── graphs │ │ ├── binary_tree.js │ │ ├── bfs.js │ │ ├── lca_as_tree.js │ │ ├── undirected_graph.js │ │ └── lca_as_graph.js │ ├── Permutation2.java │ └── Permutation.java └── codility │ └── binary_sum.js ├── LICENSE └── README.md /src/leetCode/two_sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/two-sum/ 3 | * 4 | * @param {number[]} nums 5 | * @param {number} target 6 | * @return {number[]} 7 | */ 8 | var twoSum = function(nums, target) { 9 | 10 | const indexes = {}; 11 | for (let i = 0; i < nums.length; ++i) { 12 | 13 | let temp = target - nums[i]; 14 | 15 | if (indexes[temp] !== undefined) { 16 | return [indexes[temp], i]; 17 | } 18 | 19 | indexes[nums[i]] = i; 20 | 21 | } 22 | 23 | }; -------------------------------------------------------------------------------- /src/leetCode/remove_duplicates_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 3 | * 4 | * @param {number[]} nums 5 | * @return {number} 6 | */ 7 | var removeDuplicates = function(nums) { 8 | 9 | let i = j = 0; 10 | for (i = 0, j = 1; j < nums.length;) { 11 | 12 | if (nums[i] === nums[j]) { 13 | j += 1; 14 | } else { 15 | i += 1; 16 | nums[i] = nums[j]; 17 | j += 1; 18 | } 19 | 20 | } 21 | 22 | return i + 1; 23 | 24 | }; -------------------------------------------------------------------------------- /src/leetCode/max_depth_binary_tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/maximum-depth-of-binary-tree/ 3 | * 4 | * Definition for a binary tree node. 5 | * function TreeNode(val) { 6 | * this.val = val; 7 | * this.left = this.right = null; 8 | * } 9 | */ 10 | /** 11 | * @param {TreeNode} root 12 | * @return {number} 13 | */ 14 | 15 | var maxDepth = function(root) { 16 | 17 | if (!root) return 0; 18 | 19 | let count = 0; 20 | count = 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); 21 | return count; 22 | 23 | }; -------------------------------------------------------------------------------- /src/leetCode/coin_change.java: -------------------------------------------------------------------------------- 1 | https://leetcode.com/problems/coin-change/ 2 | 3 | class Solution { 4 | public int coinChange(int[] coins, int amount) { 5 | 6 | int max = amount + 1; 7 | int[] dp = new int[amount + 1]; 8 | Arrays.fill(dp, max); 9 | dp[0] = 0; 10 | for (int i = 1; i <= amount; i++) { 11 | for (int j = 0; j < coins.length; j++) { 12 | if (coins[j] <= i) { 13 | dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); 14 | } 15 | } 16 | } 17 | return dp[amount] > amount ? -1 : dp[amount]; 18 | } 19 | } -------------------------------------------------------------------------------- /src/leetCode/min_deletion_size.js: -------------------------------------------------------------------------------- 1 | var minDeletionSize = function(A) { 2 | 3 | if (A.length === 1) return 0; 4 | 5 | const columns = new Array(A[0].length); 6 | 7 | for (let i = 0; i < columns.length; i += 1) { 8 | columns[i] = new Array(); 9 | } 10 | 11 | 12 | for (let i = 0; i < A.length; i += 1) { 13 | 14 | const letter = A[i].split(''); 15 | 16 | for (let j = 0; j < letter.length; j += 1) { 17 | columns[j].push(letter[j]); 18 | } 19 | 20 | } 21 | 22 | console.log(columns); 23 | 24 | return 0; 25 | 26 | }; 27 | 28 | minDeletionSize(["ca","bb","ac"]); -------------------------------------------------------------------------------- /src/classic/sorting/quick_sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {int} array 3 | */ 4 | 5 | function quickSort(array) { 6 | 7 | if (array.length <= 1) { 8 | return array; 9 | } else { 10 | 11 | var left = []; 12 | var right = []; 13 | var newArray = []; 14 | var pivot = array.pop(); 15 | var length = array.length; 16 | 17 | for (var i = 0; i < length; i++) { 18 | if (array[i] <= pivot) { 19 | left.push(array[i]); 20 | } else { 21 | right.push(array[i]); 22 | } 23 | } 24 | 25 | return newArray.concat(quickSort(left), pivot, quickSort(right)); 26 | } 27 | } 28 | 29 | const test = [170, 45, 75, 90, 802, 24, 2, 66]; 30 | const sortedArr = quickSort(test); 31 | console.log(sortedArr); -------------------------------------------------------------------------------- /src/leetCode/minIncrement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/minimum-increment-to-make-array-unique/ 3 | * 4 | * @param {number[]} A 5 | * @return {number} 6 | */ 7 | var minIncrementForUnique = function(A) { 8 | 9 | if (A.length < 2) return 0; 10 | 11 | let changes = 0; 12 | 13 | A.sort((a, b) => a - b); 14 | 15 | for (let i = 0, j = i + 1; j < A.length; ++i, ++j) { 16 | if (A[i] === A[j]) { 17 | A[j] += 1; 18 | changes += 1; 19 | } else if (A[i] > A[j]) { 20 | const temp = A[j]; 21 | A[j] = A[i] + 1; 22 | changes += A[j] - temp; 23 | } 24 | 25 | } 26 | 27 | return changes; 28 | 29 | }; -------------------------------------------------------------------------------- /src/leetCode/linked_list_cycle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/linked-list-cycle/ 3 | * 4 | * Definition for singly-linked list. 5 | * function ListNode(val) { 6 | * this.val = val; 7 | * this.next = null; 8 | * } 9 | */ 10 | 11 | /** 12 | * @param {ListNode} head 13 | * @return {boolean} 14 | */ 15 | var hasCycle = function(head) { 16 | 17 | let slowPointer = fastPointer = head; 18 | while (slowPointer !== null && fastPointer !== null && fastPointer.next !== null) { 19 | 20 | slowPointer = slowPointer.next; 21 | fastPointer = fastPointer.next.next; 22 | 23 | if (slowPointer === fastPointer) { 24 | return true; 25 | } 26 | 27 | } 28 | 29 | return false; 30 | 31 | }; -------------------------------------------------------------------------------- /src/leetCode/binary_tree_inorder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/binary-tree-inorder-traversal/ 3 | * 4 | * Definition for a binary tree node. 5 | * function TreeNode(val) { 6 | * this.val = val; 7 | * this.left = this.right = null; 8 | * } 9 | */ 10 | /** 11 | * @param {TreeNode} root 12 | * @return {number[]} 13 | */ 14 | 15 | var inorderTraversal = function(root) { 16 | 17 | const res = []; 18 | const stack = []; 19 | let curr = root; 20 | 21 | while (curr != null || !(stack.length === 0)) { 22 | 23 | while (curr != null) { 24 | stack.push(curr); 25 | curr = curr.left; 26 | } 27 | 28 | curr = stack.pop(); 29 | res.push(curr.val); 30 | curr = curr.right; 31 | 32 | } 33 | 34 | return res; 35 | 36 | }; -------------------------------------------------------------------------------- /src/leetCode/swap_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/permutations/ 3 | */ 4 | function swap(arr, i, j) { 5 | 6 | const temp = arr[i]; 7 | arr[i] = arr[j]; 8 | arr[j] = temp; 9 | 10 | } 11 | 12 | function permutation(arr, l, r, combinations) { 13 | 14 | if (l === r) { 15 | combinations.push(new Array(...arr)); 16 | } else { 17 | 18 | for (let i = l; i <= r; ++i) { 19 | 20 | swap(arr, l, i); 21 | permutation(arr, l + 1, r, combinations); 22 | swap(arr, l, i); 23 | 24 | } 25 | 26 | } 27 | 28 | } 29 | 30 | var permute = function(arr) { 31 | 32 | if (arr.length === 1) return [arr]; 33 | 34 | const n = arr.length; 35 | const combinations = []; 36 | 37 | permutation(arr, 0, n - 1, combinations); 38 | return combinations; 39 | 40 | } -------------------------------------------------------------------------------- /src/leetCode/reverse_string_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/reverse-string-ii/ 3 | * 4 | * @param {string} s 5 | * @param {number} k 6 | * @return {string} 7 | */ 8 | 9 | function reverse(arr, start, end) { 10 | 11 | for (let i = start, j = end; i <= j; ++i, --j) { 12 | 13 | const temp = arr[i]; 14 | arr[i] = arr[j]; 15 | arr[j] = temp; 16 | 17 | } 18 | 19 | } 20 | 21 | var reverseStr = function(s, k) { 22 | 23 | const windowSize = 2 * k; 24 | const sLenght = s.length; 25 | const tokenized = s.split(''); 26 | 27 | if (k >= sLenght) { 28 | reverse(tokenized, 0, sLenght - 1); 29 | } else { 30 | for (let i = 0; i <= sLenght; i += windowSize) { 31 | reverse(tokenized, i, Math.min(i + k - 1, sLenght - 1)); 32 | } 33 | } 34 | 35 | return tokenized.join(''); 36 | 37 | }; -------------------------------------------------------------------------------- /src/classic/permutations.js: -------------------------------------------------------------------------------- 1 | function swap(arr, i, j) { 2 | 3 | const temp = arr[i]; 4 | arr[i] = arr[j]; 5 | arr[j] = temp; 6 | 7 | } 8 | 9 | function permutation(arr, l, r, combinations) { 10 | 11 | if (l === r) { 12 | combinations.push(new Array(...arr)); 13 | } else { 14 | 15 | for (let i = l; i <= r; ++i) { 16 | 17 | swap(arr, l, i); 18 | permutation(arr, l + 1, r, combinations); 19 | swap(arr, l, i); 20 | 21 | } 22 | 23 | } 24 | 25 | } 26 | 27 | var permute = function(arr) { 28 | 29 | const n = arr.length; 30 | const combinations = []; 31 | 32 | permutation(arr, 0, n - 1, combinations); 33 | return combinations; 34 | 35 | } 36 | 37 | const test = ['A', 'B', 'C', 'D']; 38 | const result = permute(test); 39 | console.log(result, result.length); -------------------------------------------------------------------------------- /src/leetCode/add_two_numbers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/add-two-numbers/ 3 | * 4 | * Definition for singly-linked list. 5 | * function ListNode(val) { 6 | * this.val = val; 7 | * this.next = null; 8 | * } 9 | */ 10 | /** 11 | * @param {ListNode} l1 12 | * @param {ListNode} l2 13 | * @return {ListNode} 14 | */ 15 | var addTwoNumbers = function(l1, l2) { 16 | 17 | let h3 = new ListNode(0); 18 | let l3 = h3; 19 | let res, carry = 0; 20 | 21 | while (l1 || l2) { 22 | res = (l1 ? l1.val : 0) + (l2 ? l2.val : 0) + carry; 23 | carry = parseInt(res / 10); 24 | l3.next = new ListNode(res % 10); 25 | l3 = l3.next; 26 | if (l1) l1 = l1.next; 27 | if (l2) l2 = l2.next; 28 | } 29 | 30 | if (carry > 0) { 31 | l3.next = new ListNode(carry); 32 | } 33 | 34 | return h3.next; 35 | 36 | }; -------------------------------------------------------------------------------- /src/leetCode/three_sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/3sum/ 3 | * 4 | * @param {*} arr 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number[][]} 9 | */ 10 | var threeSum = function(arr) { 11 | if (arr.length < 3) return []; 12 | 13 | arr.sort((a, b) => a - b); 14 | 15 | let n = arr.length; 16 | const triplets = new Set(); 17 | 18 | for (let i = 0; i < n; ++i) { 19 | let l = i + 1; 20 | let r = n - 1; 21 | let x = arr[i]; 22 | 23 | while (l < r) { 24 | const sum = x + arr[l] + arr[r]; 25 | 26 | if (sum === 0) { 27 | triplets.add([x, arr[l], arr[r]].join("::")); 28 | l += 1; 29 | r -= 1; 30 | } else if (sum < 0) { 31 | l += 1; 32 | } else { 33 | r -= 1; 34 | } 35 | } 36 | } 37 | 38 | return Array.from(triplets).map(a => a.split("::").map(b => parseInt(b))); 39 | }; -------------------------------------------------------------------------------- /src/leetCode/lca_binary_tree.java: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ 3 | * 4 | * Definition for a binary tree node. 5 | * public class TreeNode { 6 | * int val; 7 | * TreeNode left; 8 | * TreeNode right; 9 | * TreeNode(int x) { val = x; } 10 | * } 11 | */ 12 | class Solution { 13 | 14 | 15 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 16 | 17 | if (root == null) return null; 18 | 19 | if (root.val == p.val || root.val == q.val) { 20 | return root; 21 | } 22 | 23 | TreeNode leftLca = lowestCommonAncestor(root.left, p, q); 24 | TreeNode rightLca = lowestCommonAncestor(root.right, p, q); 25 | 26 | if (leftLca != null && rightLca != null) { 27 | return root; 28 | } 29 | 30 | return leftLca == null ? rightLca : leftLca; 31 | 32 | } 33 | } -------------------------------------------------------------------------------- /src/leetCode/odd_even_linkedlist.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/odd-even-linked-list/ 3 | * 4 | * Definition for singly-linked list. 5 | * function ListNode(val) { 6 | * this.val = val; 7 | * this.next = null; 8 | * } 9 | */ 10 | /** 11 | * @param {ListNode} head 12 | * @return {ListNode} 13 | */ 14 | var oddEvenList = function(head) { 15 | 16 | if (!head || !head.next) return head 17 | 18 | const oddHead = head; 19 | const evenHead = head.next; 20 | let oddPos = oddHead; 21 | let evenPos = evenHead; 22 | 23 | while (oddPos.next.next) { 24 | 25 | oddPos.next = oddPos.next.next; 26 | oddPos = oddPos.next; 27 | 28 | if (!evenPos.next.next) { 29 | oddPos.next = evenHead; 30 | evenPos.next = null; 31 | return oddHead; 32 | } 33 | 34 | evenPos.next = evenPos.next.next; 35 | evenPos = evenPos.next; 36 | } 37 | 38 | oddPos.next = evenHead; 39 | return oddHead; 40 | 41 | } -------------------------------------------------------------------------------- /src/leetCode/first_bad_version.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/first-bad-version/ 3 | * 4 | * Definition for isBadVersion() 5 | * 6 | * @param {integer} version number 7 | * @return {boolean} whether the version is bad 8 | * isBadVersion = function(version) { 9 | * ... 10 | * }; 11 | */ 12 | 13 | /** 14 | * @param {function} isBadVersion() 15 | * @return {function} 16 | */ 17 | var solution = function(isBadVersion) { 18 | /** 19 | * @param {integer} n Total versions 20 | * @return {integer} The first bad version 21 | */ 22 | return function(n) { 23 | 24 | let start = mid = 0; 25 | let end = n; 26 | 27 | while (start <= end) { 28 | 29 | mid = Math.floor((start + end) / 2); 30 | if (isBadVersion(mid)) { 31 | end = mid - 1; 32 | } else { 33 | start = mid + 1; 34 | } 35 | 36 | } 37 | 38 | return start; 39 | 40 | }; 41 | 42 | }; -------------------------------------------------------------------------------- /src/leetCode/max_profit_DP.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ 3 | * @param {*} prices 4 | */ 5 | var maxProfit = function(prices) { 6 | 7 | if (prices.length < 2) return 0; 8 | 9 | let minPrice = prices[0]; 10 | let maxProfitVal = Number.MIN_SAFE_INTEGER; 11 | for (let i = 1; i < prices.length; ++i) { 12 | if (prices[i] - minPrice > maxProfitVal) maxProfitVal = prices[i] - minPrice; 13 | if (prices[i] < minPrice) minPrice = prices[i]; 14 | } 15 | return maxProfitVal; 16 | }; 17 | 18 | console.log(maxProfit([7,1,5,2,3,6,4])); // 5 19 | console.log(maxProfit([7,6,4,3,1])); // 0 20 | console.log(maxProfit([3,2,6,5,0,3])); // 4 21 | console.log(maxProfit([2,4,1])); // 2 22 | console.log(maxProfit([1,2,4,2,5,7,2,4,9,0])); // 8 23 | console.log(maxProfit([4,7,2,1])); // 3 24 | console.log(maxProfit([2,11,1,4,7])); // 9 25 | console.log(maxProfit([2,1,2,1,0,1,2])); // 2 26 | console.log(maxProfit([3,3,5,0,0,3,1,4])); // 4 -------------------------------------------------------------------------------- /src/classic/linkedList/linked_list.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(value) { 3 | this.value = value; 4 | this.next = null; 5 | } 6 | } 7 | 8 | 9 | class LinkedList { 10 | constructor (){ 11 | this.head = null; 12 | this.nodes = 0; 13 | } 14 | 15 | addNode(v) { 16 | 17 | this.nodes += 1; 18 | 19 | if (!this.head) { 20 | this.head = new Node(v); 21 | return; 22 | } 23 | 24 | let pointer = this.head; 25 | 26 | while (pointer.next !== null) { 27 | pointer = pointer.next; 28 | } 29 | 30 | pointer.next = new Node(v); 31 | } 32 | 33 | print() { 34 | 35 | let pointer = this.head; 36 | let string = ''; 37 | 38 | while (pointer != null) { 39 | string += `${pointer.value} -> `; 40 | pointer = pointer.next; 41 | } 42 | 43 | string += `//`; 44 | console.log(string); 45 | 46 | } 47 | } 48 | 49 | const ll = new LinkedList(); 50 | ll.addNode(1); 51 | ll.addNode(3); 52 | ll.addNode(2); 53 | 54 | ll.print(); -------------------------------------------------------------------------------- /src/classic/sorting/heap_sort2.js: -------------------------------------------------------------------------------- 1 | function heapify(array, n, i) { 2 | 3 | let largest = i; 4 | const left = 2 * i + 1; 5 | const right = 2 * i + 2; 6 | 7 | if (left < n && array[left] > array[largest]) { 8 | largest = left; 9 | } 10 | 11 | if (right < n && array[right] > array[largest]) { 12 | largest = right; 13 | } 14 | 15 | if (largest !== i) { 16 | 17 | const temp = array[i]; 18 | array[i] = array[largest]; 19 | array[largest] = temp; 20 | 21 | heapify(array, n, largest); 22 | 23 | } 24 | 25 | } 26 | 27 | function heapSort(array, ascendingOrder) { 28 | 29 | // create max heap 30 | for (let i = parseInt(array.length / 2); i >= 0; i--) { 31 | heapify(array, array.length, i); 32 | } 33 | 34 | for (let i = array.length - 1; i > 0; i--) { 35 | 36 | const temp = array[0]; 37 | array[0] = array[i]; 38 | array[i] = temp; 39 | 40 | heapify(array, i, 0); 41 | 42 | } 43 | 44 | return array; 45 | 46 | } 47 | 48 | console.log(heapSort([4, 1, 3, 10, 5])); 49 | -------------------------------------------------------------------------------- /src/leetCode/valid_parenthesis.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/valid-parentheses/ 3 | * @param {*} s 4 | */ 5 | var isValid = function(s) { 6 | 7 | const tokensMap = { 8 | '(': ')', 9 | '[': ']', 10 | '{': '}' 11 | }; 12 | 13 | const stack = []; 14 | let validTokens = 0; 15 | 16 | const splittedS = s.split(''); 17 | for (let i = 0; i < splittedS.length; ++i) { 18 | 19 | const currentToken = splittedS[i]; 20 | 21 | if (tokensMap[currentToken]) { 22 | stack.push(currentToken); 23 | } else { 24 | 25 | const expectedCloseToken = tokensMap[stack.pop()]; 26 | 27 | if (expectedCloseToken === currentToken) { 28 | validTokens += 1; 29 | } 30 | 31 | } 32 | 33 | } 34 | 35 | return validTokens === s.length / 2; 36 | 37 | }; 38 | 39 | console.log(isValid('')); 40 | console.log(isValid('[')); 41 | console.log(isValid('()')); 42 | console.log(isValid('()[]{}')); 43 | console.log(isValid('(]')); 44 | console.log(isValid('([)]')); 45 | console.log(isValid('{[]}')); -------------------------------------------------------------------------------- /src/classic/string/kmp.js: -------------------------------------------------------------------------------- 1 | function computeLPS(pattern) { 2 | 3 | let lps = [0]; 4 | let len = 0; 5 | let i = 1; 6 | 7 | while (i < pattern.length) { 8 | 9 | if (pattern[i] === pattern[len]) { 10 | len++; 11 | lps[i] = len; 12 | i++; 13 | } else { 14 | 15 | if (len != 0) { 16 | len = lps[len - 1]; 17 | } else { 18 | 19 | lps[i] = len; 20 | i++; 21 | 22 | } 23 | 24 | } 25 | 26 | } 27 | 28 | return lps; 29 | 30 | } 31 | 32 | function kmp(word, pattern) { 33 | 34 | let lps = computeLPS(pattern); 35 | 36 | for (let i = 0, j = 0; i < word.length;) { 37 | 38 | if (word.charAt(i) === pattern.charAt(j)) { 39 | ++i; 40 | ++j; 41 | } 42 | 43 | if (j === pattern.length) { 44 | console.log(`Pattern found at index ${i - pattern.length}`); 45 | j = lps[j - 1]; 46 | } else if (i < word.length && word.charAt(i) !== pattern.charAt(j)) { 47 | 48 | if (j !== 0) { 49 | j = lps[j - 1]; 50 | } else { 51 | ++i; 52 | } 53 | 54 | } 55 | 56 | } 57 | 58 | } 59 | 60 | kmp('AAAAABAAAABA', 'BA'); -------------------------------------------------------------------------------- /src/classic/graphs/binary_tree.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(value) { 3 | this.value = value; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | } 8 | 9 | class BinaryTree { 10 | constructor() { 11 | this.root = null; 12 | } 13 | 14 | addUtils(currentNode, newNode) { 15 | 16 | if (newNode.value < currentNode.value) { 17 | if (!currentNode.left) { 18 | currentNode.left = newNode; 19 | } else { 20 | this.addUtils(currentNode.left, newNode); 21 | } 22 | } else { 23 | if (!currentNode.right) { 24 | currentNode.right = newNode; 25 | } else { 26 | this.addUtils(currentNode.right, newNode); 27 | } 28 | } 29 | } 30 | 31 | addNode(value) { 32 | 33 | const newNode = new Node(value); 34 | 35 | if (!this.root) { 36 | this.root = newNode; 37 | } else { 38 | this.addUtils(this.root, newNode); 39 | } 40 | 41 | } 42 | 43 | getRoot() { 44 | return this.root; 45 | } 46 | } 47 | 48 | const tree = new BinaryTree(); 49 | tree.addNode(5); 50 | tree.addNode(2); 51 | tree.addNode(8); 52 | tree.addNode(4); 53 | tree.addNode(10); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Juan Pablo Rivillas Ospina 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/classic/sorting/insertion_sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Complexity of the algorithm is n^2 because 3 | * in the worst case the array will be reverse 4 | * ordered and it will take n swaps over the n 5 | * elements. 6 | * 7 | * @param {int} array 8 | */ 9 | 10 | function insertionSort(array) { 11 | 12 | let length = array.length; 13 | let pointer = 1; 14 | 15 | for (let i = 1; i < length; i++) { 16 | 17 | for (let j = pointer; j > 0; j--) { 18 | 19 | // swap items if previous item is lower 20 | if (array[j] < array[j - 1]) { 21 | 22 | const temp = array[j - 1]; 23 | array[j-1] = array[j]; 24 | array[j] = temp; 25 | 26 | } else { 27 | /** 28 | * Whenever it reaches a position in which the previous item 29 | * is no longer greater or it reaches the first position, it 30 | * should stop. 31 | */ 32 | break; 33 | } 34 | 35 | } 36 | 37 | pointer++; 38 | 39 | } 40 | 41 | return array; 42 | 43 | } 44 | 45 | console.log(insertionSort([38, 27, 43, 3, 9, 82, 10])); 46 | console.log(insertionSort([38, 27, 43, 3, 9, 82, 10, 1, 2, 3])); 47 | console.log(insertionSort([1, 2, 3, 4, 5, 6])); 48 | console.log(insertionSort([6, 5, 4, 3, 2, 1])); -------------------------------------------------------------------------------- /src/leetCode/shortest_completing_word.java: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/shortest-completing-word/ 2 | 3 | class Solution { 4 | 5 | public int[] count(String word) { 6 | 7 | int[] ans = new int[26]; 8 | 9 | for (char letter: word.toCharArray()) { 10 | 11 | int index = Character.toLowerCase(letter) - 'a'; 12 | 13 | if (index >= 0 && index < 26) { 14 | ans[index] += 1; 15 | } 16 | 17 | } 18 | 19 | return ans; 20 | 21 | } 22 | 23 | public boolean dominates(int[] currentWord, int[] target) { 24 | for (int i = 0; i < currentWord.length; ++i) { 25 | if (currentWord[i] < target[i]) return false; 26 | } 27 | return true; 28 | } 29 | 30 | public String shortestCompletingWord(String licensePlate, String[] words) { 31 | 32 | int[] target = count(licensePlate); 33 | String ans = ""; 34 | 35 | for (int i = 0; i < words.length; ++i) { 36 | if ((words[i].length() < ans.length() || ans.length() == 0) && 37 | dominates(count(words[i]), target)) { 38 | ans = words[i]; 39 | } 40 | } 41 | 42 | return ans; 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /src/classic/graphs/bfs.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(value) { 3 | this.data = value; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | } 8 | 9 | class Queue { 10 | constructor() { 11 | this.queue = []; 12 | } 13 | 14 | add(value) { 15 | this.queue.unshift(value); 16 | } 17 | 18 | isEmpty() { 19 | return this.queue.length === 0; 20 | } 21 | 22 | poll() { 23 | return this.queue.pop(); 24 | } 25 | 26 | print() { 27 | for (let i = this.queue.length - 1; i >= 0; i--) { 28 | console.log(this.queue[i]); 29 | } 30 | } 31 | } 32 | 33 | const bfs = (tree) => { 34 | 35 | const queue = new Queue(); 36 | queue.add(tree.root); 37 | 38 | while (!queue.isEmpty()) 39 | { 40 | 41 | const tempNode = queue.poll(); 42 | console.log(tempNode.data + " "); 43 | 44 | if (tempNode.left) queue.add(tempNode.left); 45 | if (tempNode.right) queue.add(tempNode.right); 46 | } 47 | 48 | } 49 | 50 | const tree = {}; 51 | tree.root = new Node(1); 52 | tree.root.left = new Node(2); 53 | tree.root.left.left = new Node(4); 54 | tree.root.left.right = new Node(5); 55 | tree.root.right = new Node(3); 56 | tree.root.right.left = new Node(6); 57 | tree.root.right.right = new Node(7); 58 | 59 | bfs(tree); 60 | -------------------------------------------------------------------------------- /src/leetCode/min_stack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/min-stack/ 3 | */ 4 | 5 | /** 6 | * initialize your data structure here. 7 | */ 8 | var MinStack = function() { 9 | this.tail = null; 10 | }; 11 | 12 | /** 13 | * @param {number} x 14 | * @return {void} 15 | */ 16 | MinStack.prototype.push = function(x) { 17 | 18 | if (!this.tail) { 19 | this.tail = { 20 | value: x, min: x, before: null 21 | }; 22 | return; 23 | } 24 | 25 | this.tail = { 26 | value: x, 27 | min: Math.min(x, this.tail.min), 28 | before: this.tail 29 | }; 30 | 31 | }; 32 | 33 | /** 34 | * @return {void} 35 | */ 36 | MinStack.prototype.pop = function() { 37 | if (this.tail) this.tail = this.tail.before; 38 | }; 39 | 40 | /** 41 | * @return {number} 42 | */ 43 | MinStack.prototype.top = function() { 44 | return this.tail ? this.tail.value : null; 45 | }; 46 | 47 | /** 48 | * @return {number} 49 | */ 50 | MinStack.prototype.getMin = function() { 51 | return this.tail ? this.tail.min : null; 52 | }; 53 | 54 | /** 55 | * Your MinStack object will be instantiated and called as such: 56 | * var obj = Object.create(MinStack).createNew() 57 | * obj.push(x) 58 | * obj.pop() 59 | * var param_3 = obj.top() 60 | * var param_4 = obj.getMin() 61 | */ -------------------------------------------------------------------------------- /src/classic/sorting/radix_sort.js: -------------------------------------------------------------------------------- 1 | function countingSort(arr, n, exp) { 2 | 3 | const output = new Array(n); 4 | const count = new Array(10); 5 | count.fill(0); 6 | output.fill(0); 7 | 8 | /** 9 | * The following expression gets the less significat digit at every step. 10 | * parseInt((arr[i]/exp)%10) 11 | * For example: 12 | * (7/1)%10 = 7 13 | * (7/10)%10 = 0 14 | * (7/100)%100 = 0 15 | * (802/1)%10 = 2 16 | * (802/10)%10 = 0 17 | * (802/100)%100 = 8 18 | */ 19 | for (let i = 0; i < n; ++i) { 20 | const pos = parseInt((arr[i]/exp)%10); 21 | count[pos] += 1; 22 | } 23 | 24 | for (let i = 1; i < 10; ++i) { 25 | count[i] = count[i] + count[i - 1]; 26 | } 27 | 28 | for (let i = n - 1; i >= 0; i--) { 29 | const pos = parseInt((arr[i]/exp)%10); 30 | output[count[ pos ] - 1] = arr[i]; 31 | count[ pos ]--; 32 | } 33 | 34 | for (i = 0; i < n; i++) { 35 | arr[i] = output[i]; 36 | } 37 | 38 | } 39 | 40 | function radixSort(arr) { 41 | 42 | const maxNumber = Math.max(...arr); 43 | const n = arr.length; 44 | 45 | for (let exp = 1; parseInt(maxNumber/exp) > 0; exp *= 10) { 46 | countingSort(arr, n, exp); 47 | } 48 | 49 | return arr; 50 | 51 | } 52 | 53 | const test = [170, 45, 75, 90, 802, 24, 2, 66]; 54 | const sortedArr = radixSort(test); 55 | console.log(sortedArr); -------------------------------------------------------------------------------- /src/leetCode/chess_queen.js: -------------------------------------------------------------------------------- 1 | function print(matrix, [y, x], [dy, dx]) { 2 | 3 | const newY = y + dy; 4 | const newX = x + dx; 5 | const isUnderBoundaries = newY < matrix.length && newX < matrix.length && newY >= 0 && newX >= 0; 6 | 7 | if (isUnderBoundaries) { 8 | 9 | // values 0 and 2 are valid positions it can take 10 | if (matrix[newY][newX] % 2 === 0){ 11 | console.log([newY, newX]); 12 | } 13 | 14 | // if the position is 2, it means it ate the element of the chess 15 | if (matrix[newY][newX] === 2) return; 16 | 17 | // invoke recursively to make the next movement 18 | print(matrix, [newY, newX], [dy, dx]); 19 | 20 | } 21 | 22 | } 23 | 24 | function queenPositions(matrix, currentPosition) { 25 | 26 | const directions = [ 27 | [0, 1], 28 | [0, -1], 29 | [-1, 0], 30 | [1, 0], 31 | [-1, 1], 32 | [-1, -1], 33 | [1, -1], 34 | [1, 1] 35 | ]; 36 | 37 | for (let i = 0; i < directions.length; i++) { 38 | print(matrix, currentPosition, directions[i]); 39 | } 40 | 41 | } 42 | 43 | /** 44 | * 0 means empty 45 | * 1 means same team element 46 | * 2 means adversary that can be eaten 47 | */ 48 | const matrix = [ 49 | [0, 0, 2, 2, 0], 50 | [0, 2, 0, 2, 0], 51 | [0, 0, 1, 0, 0], 52 | [1, 1, 0, 0, 0], 53 | [1, 1, 1, 1, 1] 54 | ]; 55 | 56 | // squared matrix 57 | console.log(queenPositions(matrix, [2, 2])); -------------------------------------------------------------------------------- /src/classic/Permutation2.java: -------------------------------------------------------------------------------- 1 | // Java program to print all permutations of a 2 | // given string. 3 | public class Permutation2 4 | { 5 | public static void main(String[] args) 6 | { 7 | String str = "AB"; 8 | int n = str.length(); 9 | Permutation2 permutation = new Permutation2(); 10 | permutation.permute(str, 0, n-1); 11 | } 12 | 13 | /** 14 | * permutation function 15 | * @param str string to calculate permutation for 16 | * @param l starting index 17 | * @param r end index 18 | */ 19 | private void permute(String str, int l, int r) 20 | { 21 | if (l == r) 22 | System.out.println(str); 23 | else 24 | { 25 | for (int i = l; i <= r; i++) 26 | { 27 | str = swap(str,l,i); 28 | permute(str, l+1, r); 29 | str = swap(str,l,i); 30 | } 31 | } 32 | } 33 | 34 | /** 35 | * Swap Characters at position 36 | * @param a string value 37 | * @param i position 1 38 | * @param j position 2 39 | * @return swapped string 40 | */ 41 | public String swap(String a, int i, int j) 42 | { 43 | char temp; 44 | char[] charArray = a.toCharArray(); 45 | temp = charArray[i] ; 46 | charArray[i] = charArray[j]; 47 | charArray[j] = temp; 48 | return String.valueOf(charArray); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/classic/graphs/lca_as_tree.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | 3 | constructor(data) { 4 | this.data = data; 5 | this.left = null; 6 | this.right = null; 7 | } 8 | 9 | } 10 | 11 | class Tree { 12 | 13 | constructor(size, root) { 14 | 15 | this.root = new Node(1); 16 | this.addNodes(size, 1, this.root); 17 | 18 | } 19 | 20 | addNodes(size, currentValue, node) { 21 | 22 | if (2 * currentValue > size) return; 23 | 24 | node.left = new Node(2 * currentValue); 25 | node.right = new Node(2 * currentValue + 1); 26 | 27 | this.addNodes(size, 2 * currentValue, node.left); 28 | this.addNodes(size, 2 * currentValue + 1, node.right); 29 | 30 | } 31 | 32 | findLCA(node, n1, n2) { 33 | 34 | if (!node) return null; 35 | 36 | if (node.data === n1 || node.data === n2) { 37 | return node; 38 | } 39 | 40 | const leftLca = this.findLCA(node.left, n1, n2); 41 | const rightLca = this.findLCA(node.right, n1, n2); 42 | 43 | if (leftLca !== null && rightLca !== null) { 44 | return node; 45 | } 46 | 47 | return leftLca || rightLca; 48 | 49 | } 50 | 51 | getRoot() { 52 | return this.root; 53 | } 54 | 55 | } 56 | 57 | const tree = new Tree(7); 58 | console.log(tree.findLCA(tree.getRoot(), 4, 5).data); 59 | console.log(tree.findLCA(tree.getRoot(), 4, 6).data); 60 | console.log(tree.findLCA(tree.getRoot(), 3, 4).data); 61 | console.log(tree.findLCA(tree.getRoot(), 2, 4).data); -------------------------------------------------------------------------------- /src/classic/string/rabin_karp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Pattern search algorithm. It uses slices of the window to search for patterns 3 | * inside a text. 4 | * Best case O(n + m) 5 | * Worst case O(n*m) 6 | */ 7 | 8 | function compareEachCharacter(word, pattern, index) { 9 | 10 | let i = 0; 11 | for (i = 0; i < pattern.length; ++i) { 12 | if (word.charAt(i + index) !== pattern.charAt(i)) break 13 | } 14 | 15 | if (i === pattern.length) console.log(`Found match at index ${index}`); 16 | 17 | } 18 | 19 | function rabinKarp(word, pattern) { 20 | 21 | if (pattern.length > word.length) return; 22 | 23 | const wLength = word.length; 24 | const pLength = pattern.length; 25 | 26 | const prime = 101; 27 | const d = 256; 28 | 29 | let h = 1; 30 | for (i = 0; i < pLength - 1; ++i) { 31 | h = (h * d) % prime; 32 | } 33 | 34 | let pHash = 0; 35 | let wHash = 0; 36 | 37 | // Calculate the first window for both pattern and word 38 | for (i = 0; i < pLength; i++) { 39 | pHash = (d * pHash + pattern.charCodeAt(i)) % prime; 40 | wHash = (d * wHash + word.charCodeAt(i)) % prime; 41 | } 42 | 43 | for (let i = 0; i < wLength - pLength; ++i) { 44 | 45 | if (pHash === wHash) { 46 | compareEachCharacter(word, pattern, i); 47 | } 48 | 49 | wHash = (d * (wHash - word.charCodeAt(i) * h) + word.charCodeAt(i + pLength) ) % prime; 50 | if (wHash < 0) wHash += prime; 51 | 52 | } 53 | 54 | } 55 | 56 | rabinKarp('GEEKSFORGEEKS', 'GEEK'); 57 | rabinKarp('AABBCCDDEE', 'CD'); -------------------------------------------------------------------------------- /src/leetCode/remove_stones.js: -------------------------------------------------------------------------------- 1 | var removeStones = function(stones) { 2 | if (stones.length < 2) return 0; 3 | 4 | let moves = 0; 5 | let sets = []; 6 | let cache = {}; 7 | 8 | for (let i = 0; i < stones.length; ++i) { 9 | 10 | const [row, col] = stones[i]; 11 | 12 | if (sets.length === 0) { 13 | sets.push([stones[i]]); 14 | cache[stones[i].join('')] = 0; 15 | } else { 16 | 17 | let found = false; 18 | for (let j = 0; j < i; ++j) { 19 | 20 | if (i === j) continue; 21 | 22 | const [row2, col2] = stones[j]; 23 | 24 | if (row === row2 || col === col2) { 25 | 26 | const position = `${row2}${col2}`; 27 | sets[cache[position]].push(stones[i]); 28 | cache[stones[i].join('')] = cache[position]; 29 | found = true; 30 | break; 31 | 32 | } 33 | 34 | } 35 | 36 | if (!found) { 37 | sets.push([stones[i]]); 38 | cache[stones[i].join('')] = sets.length - 1; 39 | 40 | } 41 | 42 | } 43 | 44 | } 45 | 46 | for (let i = 0; i < sets.length; ++i) { 47 | moves += sets[i].length - 1; 48 | } 49 | 50 | return moves; 51 | 52 | }; 53 | 54 | console.log(removeStones([[3,2],[3,1],[4,4],[1,1],[0,2],[4,0]])); 55 | // console.log(removeStones([[0, 1], [1, 2], [1, 3], [3, 3], [2, 3], [0, 2]])); 56 | // console.log(removeStones([[0, 0], [0, 2], [1, 1], [2, 0], [2, 2]])); 57 | -------------------------------------------------------------------------------- /src/leetCode/shuffle_array.java: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/shuffle-an-array/ 3 | * 4 | * Your Solution object will be instantiated and called as such: 5 | * Solution obj = new Solution(nums); 6 | * int[] param_1 = obj.reset(); 7 | * int[] param_2 = obj.shuffle(); 8 | */ 9 | 10 | class Solution { 11 | 12 | int[] original; 13 | int[] structure; 14 | 15 | public Solution(int[] nums) { 16 | this.original = nums.clone(); 17 | this.structure = nums; 18 | } 19 | 20 | /** Resets the array to its original configuration and return it. */ 21 | public int[] reset() { 22 | return this.original; 23 | } 24 | 25 | /** Returns a random shuffling of the array. */ 26 | public int[] shuffle() { 27 | 28 | Queue queue = new LinkedList(); 29 | int N = this.structure.length; 30 | int[] shuffledArray = new int[N]; 31 | 32 | for (int i = 0; i < N; ++i) { 33 | queue.add(structure[i]); 34 | } 35 | 36 | Random rand = new Random(); 37 | 38 | while (!queue.isEmpty()) { 39 | 40 | Integer currentNumber = queue.poll(); 41 | boolean inserted = false; 42 | 43 | while (!inserted) { 44 | 45 | int randomPosition = rand.nextInt(N); 46 | 47 | if (shuffledArray[randomPosition] == 0) { 48 | shuffledArray[randomPosition] = currentNumber; 49 | inserted = true; 50 | } 51 | 52 | } 53 | 54 | } 55 | 56 | return shuffledArray; 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/leetCode/stack_using_queues.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/implement-stack-using-queues/ 3 | */ 4 | class Queue { 5 | 6 | constructor() { 7 | this.queue = []; 8 | } 9 | 10 | pushBack(x) { 11 | this.queue.unshift(x); 12 | } 13 | 14 | pop() { 15 | return this.queue.shift(); 16 | } 17 | 18 | top() { 19 | return this.queue[0]; 20 | } 21 | 22 | size() { 23 | return this.queue.length; 24 | } 25 | 26 | empty() { 27 | return this.queue.length === 0; 28 | } 29 | 30 | } 31 | 32 | 33 | /** 34 | * Initialize your data structure here. 35 | */ 36 | var MyStack = function() { 37 | this.queue = new Queue(); 38 | }; 39 | 40 | /** 41 | * Push element x onto stack. 42 | * @param {number} x 43 | * @return {void} 44 | */ 45 | MyStack.prototype.push = function(x) { 46 | this.queue.pushBack(x); 47 | }; 48 | 49 | /** 50 | * Removes the element on top of the stack and returns that element. 51 | * @return {number} 52 | */ 53 | MyStack.prototype.pop = function() { 54 | return this.queue.pop(); 55 | }; 56 | 57 | /** 58 | * Get the top element. 59 | * @return {number} 60 | */ 61 | MyStack.prototype.top = function() { 62 | return this.queue.top(); 63 | }; 64 | 65 | /** 66 | * Returns whether the stack is empty. 67 | * @return {boolean} 68 | */ 69 | MyStack.prototype.empty = function() { 70 | return this.queue.empty(); 71 | }; 72 | 73 | /** 74 | * Your MyStack object will be instantiated and called as such: 75 | * var obj = Object.create(MyStack).createNew() 76 | * obj.push(x) 77 | * var param_2 = obj.pop() 78 | * var param_3 = obj.top() 79 | * var param_4 = obj.empty() 80 | */ -------------------------------------------------------------------------------- /src/leetCode/alien_dictionary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/verifying-an-alien-dictionary/ 3 | */ 4 | 5 | /** 6 | * @param {string[]} words 7 | * @param {string} order 8 | * @return {boolean} 9 | */ 10 | function compare(letterA, letterB, orderMap) { 11 | 12 | const minLength = Math.min(letterA.length, letterB.length); 13 | let isOrdered = true; 14 | let diffCount = 0; 15 | 16 | for (let i = 0; i < minLength; i++) { 17 | 18 | if (orderMap[letterA[i]] !== orderMap[letterB[i]]) { 19 | 20 | diffCount += 1; 21 | 22 | if (orderMap[letterA[i]] > orderMap[letterB[i]]) { 23 | isOrdered = false; 24 | } else { 25 | isOrdered = true; 26 | } 27 | 28 | break; 29 | 30 | } 31 | 32 | } 33 | 34 | // This covers the last case in which both letteres start with the same prefix 35 | // but the length of the first is greater, then is not ordered 36 | if (diffCount === 0 && letterA.length > letterB.length) { 37 | isOrdered = false; 38 | } 39 | 40 | return isOrdered; 41 | 42 | } 43 | 44 | var isAlienSorted = function(words, order) { 45 | 46 | const orderMap = {}; 47 | 48 | order.split('').forEach((letter, index) => { 49 | orderMap[letter] = index; 50 | }); 51 | 52 | let isOrdered = true; 53 | 54 | for (let i = 0, j = 1; j < words.length; i++, j++) { 55 | 56 | if (!compare(words[i].split(''), words[j].split(''), orderMap)) { 57 | isOrdered = false; 58 | break; 59 | } 60 | 61 | } 62 | 63 | return isOrdered; 64 | 65 | }; -------------------------------------------------------------------------------- /src/codility/binary_sum.js: -------------------------------------------------------------------------------- 1 | function sumBinary(a, b) { 2 | 3 | let aBinary = (a >>> 0).toString(2); 4 | let bBinary = (b >>> 0).toString(2); 5 | 6 | let aLength = aBinary.length; 7 | let bLength = bBinary.length; 8 | const max = Math.max(aLength, bLength); 9 | 10 | for (let i = max; i > aLength; --i ) { 11 | aBinary = `0${aBinary}`; 12 | } 13 | 14 | for (let i = max; i > bLength; --i ) { 15 | bBinary = `0${bBinary}`; 16 | } 17 | 18 | aBinary = aBinary.split('').map(a => parseInt(a)); 19 | bBinary = bBinary.split('').map(a => parseInt(a)); 20 | 21 | let carry = 0; 22 | let result = []; 23 | 24 | for (let i = max - 1; i >= 0; --i) { 25 | 26 | const first = aBinary[i]; 27 | const last = bBinary[i]; 28 | 29 | result.unshift(first ^ last ^ carry); 30 | 31 | if (first === 1 && last === 1) { 32 | carry = 1; 33 | } else if (first + carry + last === 2) { 34 | carry = 1; 35 | } else { 36 | carry = 0; 37 | } 38 | 39 | } 40 | 41 | if (carry === 1) result.unshift(1); 42 | return result.join(''); 43 | 44 | } 45 | 46 | expected = (8 >>> 0).toString(2); 47 | test = sumBinary(5, 3); 48 | console.log(expected, test); 49 | 50 | expected = (30 >>> 0).toString(2); 51 | test = sumBinary(20, 10); 52 | console.log(expected, test); 53 | 54 | expected = (7 >>> 0).toString(2); 55 | test = sumBinary(5, 2); 56 | console.log(expected, test); 57 | 58 | expected = (2000 >>> 0).toString(2); 59 | test = sumBinary(500, 1500); 60 | console.log(expected, test); 61 | 62 | expected = (433 >>> 0).toString(2); 63 | test = sumBinary(328, 105); 64 | console.log(expected, test); 65 | 66 | expected = (177 >>> 0).toString(2); 67 | test = sumBinary(128, 49); 68 | console.log(expected, test); -------------------------------------------------------------------------------- /src/leetCode/max_profit.js: -------------------------------------------------------------------------------- 1 | var findMin = function(prices, start, end) { 2 | 3 | let min = Number.MAX_SAFE_INTEGER; 4 | let minIndex = null; 5 | 6 | for (let i = start; i < end; ++i) { 7 | if (prices[i] < min) { 8 | min = prices[i]; 9 | minIndex = i; 10 | } 11 | } 12 | 13 | return [min, minIndex]; 14 | 15 | }; 16 | 17 | var maxProfit = function(prices) { 18 | 19 | let indexMap = {}; 20 | prices.forEach((el, i) => { 21 | if (indexMap[el]) { 22 | indexMap[el].push(i); 23 | } else { 24 | indexMap[el] = [i]; 25 | } 26 | }); 27 | 28 | let orderedPrices = new Set(); 29 | prices.forEach(el => orderedPrices.add(el)); 30 | orderedPrices = Array.from(orderedPrices); 31 | orderedPrices.sort((a, b) => b - a); 32 | 33 | let start = 0; 34 | let end = prices.length; 35 | let maxProfitVal = Number.MIN_SAFE_INTEGER; 36 | 37 | for (let i = 0; i < orderedPrices.length; ++i) { 38 | 39 | let max = orderedPrices[i]; 40 | let maxIndex = indexMap[max].pop(); 41 | end = maxIndex; 42 | 43 | let [min, minIndex] = findMin(prices, start, end); 44 | 45 | if (minIndex !== null) { 46 | start = minIndex; 47 | maxProfitVal = Math.max(maxProfitVal, prices[end] - prices[start]); 48 | } 49 | 50 | } 51 | 52 | return Math.max(maxProfitVal, 0); 53 | 54 | }; 55 | 56 | console.log(maxProfit([7,1,5,2,3,6,4])); // 5 57 | console.log(maxProfit([7,6,4,3,1])); // 0 58 | console.log(maxProfit([3,2,6,5,0,3])); // 4 59 | console.log(maxProfit([2,4,1])); // 2 60 | console.log(maxProfit([1,2,4,2,5,7,2,4,9,0])); // 8 61 | console.log(maxProfit([4,7,2,1])); // 3 62 | console.log(maxProfit([2,11,1,4,7])); // 9 63 | console.log(maxProfit([2,1,2,1,0,1,2])); // 2 64 | console.log(maxProfit([3,3,5,0,0,3,1,4])); // 4 -------------------------------------------------------------------------------- /src/classic/sorting/heap_sort.js: -------------------------------------------------------------------------------- 1 | function heapify(array, i) { 2 | 3 | const node = array[i - 1]; 4 | const nodePosition = i - 1; 5 | const leftChild = 2 * i; 6 | const rightChild = 2 * i + 1; 7 | 8 | if (array[leftChild - 1] && node < array[leftChild - 1]) { 9 | //swap 10 | const temp = array[nodePosition]; 11 | array[nodePosition] = array[leftChild - 1]; 12 | array[leftChild - 1] = temp; 13 | heapify(array, leftChild); 14 | 15 | } else if (array[rightChild - 1] && node < array[rightChild - 1]) { 16 | //swap 17 | const temp = array[nodePosition]; 18 | array[nodePosition] = array[rightChild - 1]; 19 | array[rightChild - 1] = temp; 20 | heapify(array, rightChild); 21 | 22 | } 23 | 24 | } 25 | 26 | function buildMaxHeap(array) { 27 | 28 | const length = array.length; 29 | 30 | // create max heap 31 | for (let i = parseInt(length / 2); i > 0; i--) { 32 | heapify(array, i); 33 | } 34 | 35 | return array; 36 | 37 | } 38 | 39 | function heapSort(array, ascendingOrder) { 40 | 41 | const orderedArray = []; 42 | 43 | let maxHeapArray = buildMaxHeap(array); 44 | console.log(maxHeapArray); 45 | 46 | const arrayLength = maxHeapArray.length; 47 | 48 | while (orderedArray.length < arrayLength) { 49 | 50 | orderedArray.push(maxHeapArray[0]); 51 | 52 | // swap first and last element 53 | maxHeapArray[0] = maxHeapArray[maxHeapArray.length - 1]; 54 | 55 | // discard last element 56 | maxHeapArray = maxHeapArray.slice(0, maxHeapArray.length - 1); 57 | 58 | // console.log(maxHeapArray); 59 | heapify(maxHeapArray, maxHeapArray[0], 1); 60 | 61 | } 62 | 63 | return maxHeapArray; 64 | // return ascendingOrder ? orderedArray.reverse() : orderedArray; 65 | 66 | } 67 | 68 | // This heap sort algorithm will sort in descending order 69 | console.log(heapSort([4, 1, 3, 10, 5], true)); 70 | -------------------------------------------------------------------------------- /src/classic/Permutation.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | // Java program to print all permutations of a 4 | // given string. 5 | public class Permutation 6 | { 7 | public Set pairs = new HashSet(); 8 | 9 | public static void main(String[] args) 10 | { 11 | String str = "1234"; 12 | int n = str.length(); 13 | Permutation permutation = new Permutation(); 14 | permutation.permute(str, 0, n-1); 15 | System.out.println(permutation.getPairs()); 16 | 17 | } 18 | 19 | /** 20 | * permutation function 21 | * @param str string to calculate permutation for 22 | * @param l starting index 23 | * @param r end index 24 | */ 25 | private void permute(String str, int l, int r) 26 | { 27 | if (l == r) { 28 | 29 | String[] singlePair = str.substring(0, 2).split(""); 30 | Integer first = Integer.parseInt(singlePair[0]); 31 | Integer last = Integer.parseInt(singlePair[1]); 32 | String pairAsString = Math.min(first, last) + "" + Math.max(first, last); 33 | this.pairs.add(pairAsString); 34 | 35 | } else { 36 | for (int i = l; i <= r; i++) 37 | { 38 | str = swap(str,l,i); 39 | permute(str, l+1, r); 40 | str = swap(str,l,i); 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * Swap Characters at position 47 | * @param a string value 48 | * @param i position 1 49 | * @param j position 2 50 | * @return swapped string 51 | */ 52 | public String swap(String a, int i, int j) 53 | { 54 | char temp; 55 | char[] charArray = a.toCharArray(); 56 | temp = charArray[i] ; 57 | charArray[i] = charArray[j]; 58 | charArray[j] = temp; 59 | return String.valueOf(charArray); 60 | } 61 | 62 | public Set getPairs() { 63 | return this.pairs; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/classic/sorting/merge_sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This sort method is called the two finger sorting algorithm. 3 | * It is applied in every step of the merge sort in which you have 4 | * to join the two ordered arrays. 5 | * It takes O(n) to order it and it's pretty straightforward: 6 | * - Compares if the first position of the first array is lower 7 | * than the other array. Depending on the result, it pushes the 8 | * lower value and increase the pointer on that array. 9 | * It repeats this process until you reach the end of one of the 10 | * arrays or when you compared all the values. 11 | * 12 | * @param {int} first 13 | * @param {int} last 14 | */ 15 | function sort(first, last) { 16 | 17 | const length = first.length + last.length; 18 | let j = 0; 19 | let k = 0; 20 | 21 | const array = new Array(); 22 | while(array.length < length) { 23 | 24 | if (first[j] && last[k]) { 25 | 26 | if (first[j] < last[k]) { 27 | array.push(first[j]); 28 | j++; 29 | } else { 30 | array.push(last[k]); 31 | k++; 32 | } 33 | 34 | } else if (!first[j]) { 35 | array.push(last[k]); 36 | k++; 37 | } else if (!last[k]) { 38 | array.push(first[j]); 39 | j++; 40 | } 41 | 42 | } 43 | 44 | return array; 45 | 46 | } 47 | 48 | function mergeSort(array) { 49 | 50 | let length = array.length; 51 | 52 | if (length === 1) { 53 | return [array[0]]; 54 | } else if (length === 2){ 55 | return [Math.min(array[0], array[1]), Math.max(array[0], array[1])] 56 | 57 | } else { 58 | 59 | const first = mergeSort(array.slice(0, parseInt(length / 2))); 60 | const last = mergeSort(array.slice(parseInt(length / 2), length)); 61 | return sort(first, last); 62 | 63 | } 64 | 65 | } 66 | 67 | console.log(mergeSort([38, 27, 43, 3, 9, 82, 10])); 68 | console.log(mergeSort([38, 27, 43, 3, 9, 82, 10, 1, 2, 3])); 69 | console.log(mergeSort([1, 2, 3, 4, 5, 6])); 70 | console.log(mergeSort([6, 5, 4, 3, 2, 1])); -------------------------------------------------------------------------------- /src/leetCode/largest_time_give_digits.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/contest/weekly-contest-113/problems/largest-time-for-given-digits/ 3 | * 4 | * @param {number[]} A 5 | * @return {string} 6 | */ 7 | 8 | function factorial(n) { 9 | if (n === 0 || n === 1 ) return n; 10 | return n * factorial(n-1); 11 | } 12 | 13 | var permute = function(nums) { 14 | 15 | if (nums.length < 2) return [nums]; 16 | if (nums.length === 2) return [[nums[0],nums[1]], [nums[1],nums[0]]]; 17 | 18 | const permutations = []; 19 | const n = nums.length; 20 | 21 | for (let i = 0; i < n; i += 1) { 22 | 23 | // swap every item to position 0 24 | const temp = nums[i]; 25 | nums[i] = nums[0]; 26 | nums[0] = temp; 27 | 28 | let innerIterations = factorial(n - 1); 29 | 30 | for (let j = n - 1; innerIterations > 0; innerIterations -= 1, j -= 1) { 31 | 32 | permutations.push(new Array(...nums)); 33 | 34 | if (j === 1) { 35 | // start over 36 | j = n - 1; 37 | } 38 | 39 | const temp = nums[j]; 40 | nums[j] = nums[j - 1]; 41 | nums[j - 1] = temp; 42 | 43 | } 44 | 45 | } 46 | 47 | return permutations; 48 | 49 | }; 50 | 51 | var largestTimeFromDigits = function(A) { 52 | 53 | const permutations = permute(A); 54 | 55 | let max = -1; 56 | let index = -1; 57 | 58 | for (let i = 0; i < permutations.length; ++i) { 59 | 60 | const number = permutations[i].join(''); 61 | 62 | if (parseInt(number) <= 2359 && parseInt(number) > parseInt(max)) { 63 | 64 | const first = permutations[i].join('').slice(0, 2); 65 | const last = permutations[i].join('').slice(2, 4); 66 | 67 | if (parseInt(first) <= 23 && parseInt(last) <= 59) { 68 | max = number; 69 | index = i; 70 | } 71 | 72 | } 73 | 74 | } 75 | 76 | if (index === -1) return ''; 77 | 78 | const first = permutations[index].join('').slice(0, 2); 79 | const last = permutations[index].join('').slice(2, 4); 80 | 81 | return first + ':' + last; 82 | 83 | }; -------------------------------------------------------------------------------- /src/leetCode/number_of_islands.java: -------------------------------------------------------------------------------- 1 | /** 2 | https://leetcode.com/problems/number-of-islands/ 3 | */ 4 | 5 | class Solution { 6 | 7 | public void dfs(int i, int j, char[][] grid) { 8 | 9 | // starting point will be root 10 | Queue queue = new LinkedList(); 11 | queue.add(new int[]{i, j}); 12 | 13 | int N = grid.length; 14 | int M = grid[0].length; 15 | 16 | while (!queue.isEmpty()) { 17 | 18 | int[] currentNode = queue.poll(); 19 | int x = currentNode[0]; 20 | int y = currentNode[1]; 21 | 22 | grid[x][y] = '0'; 23 | 24 | int up = x - 1; 25 | int down = x + 1; 26 | int left = y - 1; 27 | int right = y + 1; 28 | 29 | // move up 30 | if (up >= 0 && grid[up][y] == '1') { 31 | queue.add(new int[]{up, y}); 32 | grid[up][y] = '0'; 33 | } 34 | 35 | // move down 36 | if (down < N && grid[down][y] == '1') { 37 | queue.add(new int[]{down, y}); 38 | grid[down][y] = '0'; 39 | } 40 | 41 | // move left 42 | if (left >= 0 && grid[x][left] == '1') { 43 | queue.add(new int[]{x, left}); 44 | grid[x][left] = '0'; 45 | } 46 | 47 | // move right 48 | if (right < M && grid[x][right] == '1') { 49 | queue.add(new int[]{x, right}); 50 | grid[x][right] = '0'; 51 | } 52 | 53 | } 54 | 55 | } 56 | 57 | public int numIslands(char[][] grid) { 58 | 59 | if (grid == null || grid.length == 0) return 0; 60 | 61 | int roots = 0; 62 | 63 | for (int i = 0; i < grid.length; ++i) { 64 | for (int j = 0; j < grid[0].length; ++j) { 65 | if (grid[i][j] == '1') { 66 | roots += 1; 67 | dfs(i, j, grid); 68 | } 69 | } 70 | } 71 | 72 | return roots; 73 | 74 | } 75 | } -------------------------------------------------------------------------------- /src/classic/graphs/undirected_graph.js: -------------------------------------------------------------------------------- 1 | class Graph { 2 | 3 | constructor() { 4 | this.adjacencyList = {}; 5 | this.vertexNumber = 0; 6 | this.visitStack = []; 7 | } 8 | 9 | addVertex(v) { 10 | this.adjacencyList[v] = []; 11 | this.vertexNumber++; 12 | } 13 | 14 | addEdge(v1, v2) { 15 | this.adjacencyList[v1].push(v2); 16 | this.adjacencyList[v2].push(v1); 17 | } 18 | 19 | getVertexNumber() { 20 | return this.vertexNumber; 21 | } 22 | 23 | print() { 24 | console.log(this.adjacencyList); 25 | } 26 | 27 | isCyclicUtil(v, visited, parent) { 28 | 29 | visited[v] = true; 30 | this.visitStack.push(v); 31 | 32 | const items = this.adjacencyList[v]; 33 | 34 | for (let i = 0; i < items.length; i++) { 35 | 36 | const neighbor = items[i]; 37 | 38 | if (!visited[neighbor]) { 39 | if (this.isCyclicUtil(neighbor, visited, v)) { 40 | return true; 41 | } 42 | } else if (neighbor != parent) { 43 | const cycle = this.visitStack.slice(this.visitStack.indexOf(neighbor), this.visitStack.length); 44 | console.log(cycle); 45 | return true; 46 | } 47 | 48 | } 49 | 50 | return false; 51 | 52 | } 53 | 54 | isCyclic() { 55 | 56 | const visited = {}; 57 | for (let [key] of Object.entries(this.adjacencyList)) { 58 | visited[key] = false; 59 | } 60 | 61 | for (let i = 0; i < this.vertexNumber; i++) { 62 | 63 | if (!visited[i]) { 64 | if (this.isCyclicUtil(i, visited, i)) { 65 | console.log('A graph was found'); 66 | } 67 | 68 | } 69 | 70 | } 71 | 72 | console.log(this.visitStack); 73 | 74 | } 75 | 76 | } 77 | 78 | const graph = new Graph(); 79 | graph.addVertex(0); 80 | graph.addVertex(1); 81 | graph.addVertex(2); 82 | graph.addVertex(3); 83 | graph.addVertex(4); 84 | graph.addVertex(5); 85 | 86 | graph.addEdge(0, 1); 87 | graph.addEdge(1, 2); 88 | graph.addEdge(2, 3); 89 | graph.addEdge(3, 4); 90 | graph.addEdge(3, 5); 91 | graph.addEdge(4, 1); 92 | graph.addEdge(4, 5); 93 | graph.addEdge(5, 0); 94 | 95 | // graph.print(); 96 | graph.isCyclic(); -------------------------------------------------------------------------------- /src/leetCode/binary_subtract.js: -------------------------------------------------------------------------------- 1 | function equalLength(x, y) { 2 | 3 | const xLength = x.length; 4 | const yLength = y.length; 5 | const maxLength = Math.max(xLength, yLength); 6 | 7 | for (let i = maxLength; i > xLength; --i) { 8 | x = `0${x}`; 9 | } 10 | 11 | for (let i = maxLength; i > yLength; --i) { 12 | y = `0${y}`; 13 | } 14 | 15 | return [x, y]; 16 | 17 | } 18 | 19 | function sumBinary(x, y) { 20 | 21 | x = (x >>> 0).toString(2); 22 | y = (y >>> 0).toString(2); 23 | 24 | // Make the binaries of equal length 25 | [x, y] = equalLength(x, y); 26 | 27 | x = x.split('').map(a => parseInt(a)); 28 | y = y.split('').map(a => parseInt(a)); 29 | 30 | let carry = 0; 31 | let result = []; 32 | 33 | for (let i = x.length - 1; i >= 0; --i) { 34 | 35 | const xValue = x[i]; 36 | const yValue = y[i]; 37 | 38 | result.unshift(xValue ^ yValue ^ carry); 39 | 40 | if (xValue === 1 && yValue === 1 || xValue + carry + yValue === 2) { 41 | carry = 1; 42 | } else { 43 | carry = 0; 44 | } 45 | 46 | } 47 | 48 | if (carry === 1) result.unshift(1); 49 | return parseInt(result.join(''), 2); 50 | 51 | } 52 | 53 | function substractBinary(a, b) { 54 | 55 | /** 56 | * Using technique of 2s Complement to subtract b from a 57 | * a - b is the same as a + (-b) 58 | * So we calculate -b and apply the normal sum 59 | */ 60 | // Convert b into -b 61 | b = sumBinary(~b, 1); 62 | const result = sumBinary(a, b); 63 | return (result >>> 0).toString(2); 64 | 65 | } 66 | 67 | expected = (8 >>> 0).toString(2); 68 | test = substractBinary(10, 2); 69 | console.log(expected, test); 70 | 71 | expected = (2 >>> 0).toString(2); 72 | test = substractBinary(5, 3); 73 | console.log(expected, test); 74 | 75 | expected = (3 >>> 0).toString(2); 76 | test = substractBinary(5, 2); 77 | console.log(expected, test); 78 | 79 | expected = (45 >>> 0).toString(2); 80 | test = substractBinary(50, 5); 81 | console.log(expected, test); 82 | 83 | expected = (223 >>> 0).toString(2); 84 | test = substractBinary(328, 105); 85 | console.log(expected, test); 86 | 87 | expected = (24 >>> 0).toString(2); 88 | test = substractBinary(25, 1); 89 | console.log(expected, test); -------------------------------------------------------------------------------- /src/classic/graphs/lca_as_graph.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This example implements the tree as a graph in order to be able 3 | * to calculate the LCA in binary and not binary trees. 4 | * This solution has O(n) complexity, but it demands extra space to store 5 | * the paths and an additional array traversal to look for the matches 6 | * in both paths. 7 | */ 8 | class Graph { 9 | 10 | constructor(n, root) { 11 | 12 | this.adjacencyList = {}; 13 | this.vertexNumber = 0; 14 | this.visitedStack = []; 15 | this.found = false; 16 | this.root = root; 17 | 18 | for (let i = 1; i <= n; ++i) { 19 | this.addVertex(i); 20 | } 21 | 22 | } 23 | 24 | addVertex(v) { 25 | this.adjacencyList[v] = []; 26 | this.vertexNumber++; 27 | } 28 | 29 | addEdge(v1, v2) { 30 | this.adjacencyList[v1].push(v2); 31 | this.adjacencyList[v2].push(v1); 32 | } 33 | 34 | reset() { 35 | this.visitedStack = []; 36 | } 37 | 38 | // The graph is traversed with DFS 39 | traverse(a, b, parent) { 40 | 41 | if (a === b) { 42 | this.visitedStack.push(a); 43 | return; 44 | } 45 | 46 | const neighbors = this.adjacencyList[a]; 47 | this.visitedStack.push(a); 48 | 49 | for (let i = 0; i < neighbors.length; ++i) { 50 | 51 | if (neighbors[i] === b) { 52 | this.visitedStack.push(neighbors[i]); 53 | this.found = true; 54 | return true; 55 | } else if (neighbors[i] !== parent) { 56 | 57 | const foundItem = this.traverse(neighbors[i], b, a); 58 | 59 | if (!foundItem) { 60 | this.visitedStack.pop(neighbors[i]); 61 | } else { 62 | return true; 63 | } 64 | 65 | } 66 | 67 | } 68 | 69 | return false; 70 | 71 | } 72 | 73 | getVisitedStack() { 74 | return this.visitedStack; 75 | } 76 | 77 | getIsItemFound() { 78 | return this.found; 79 | } 80 | 81 | getRoot() { 82 | return this.root; 83 | } 84 | 85 | } 86 | 87 | function findLCA(input, n1, n2) { 88 | 89 | const data = input.split('\n'); 90 | const [n, q] = data[0].split(' '); 91 | const graph = new Graph(n, '1'); 92 | 93 | for (let i = 1; i < n; ++i) { 94 | const [a, b] = data[i].split(' '); 95 | graph.addEdge(a, b); 96 | } 97 | 98 | graph.traverse(graph.getRoot(), n1, graph.getRoot()); 99 | const path1 = graph.getVisitedStack(); 100 | graph.reset(); 101 | 102 | graph.traverse(graph.getRoot(), n2, graph.getRoot()); 103 | const path2 = graph.getVisitedStack(); 104 | graph.reset(); 105 | 106 | let LCA = null; 107 | for (let i = 0, j = 0; i < path1.length, j < path2.length; ++i, ++j) { 108 | 109 | if (path1[i] === path2[j]) { 110 | LCA = path1[i]; 111 | } 112 | 113 | } 114 | 115 | // LCA stands for Lowest Common Ancestor 116 | return LCA; 117 | 118 | } 119 | 120 | // Not binary tree 121 | const test = `10 3 122 | 1 2 123 | 1 3 124 | 1 4 125 | 3 5 126 | 3 6 127 | 3 7 128 | 4 8 129 | 8 9 130 | 9 10`; 131 | 132 | findLCA(test, '1', '4'); 133 | findLCA(test, '1', '5'); 134 | findLCA(test, '2', '9'); 135 | findLCA(test, '5', '7'); 136 | 137 | // Binary Tree 138 | const test2 = `7 3 139 | 1 2 140 | 1 3 141 | 2 4 142 | 2 5 143 | 3 6 144 | 3 7`; 145 | 146 | findLCA(test2, '4', '5'); 147 | findLCA(test2, '4', '6'); 148 | findLCA(test2, '3', '4'); 149 | findLCA(test2, '2', '4'); 150 | -------------------------------------------------------------------------------- /src/leetCode/kitty_distance.js: -------------------------------------------------------------------------------- 1 | class Graph { 2 | 3 | constructor(n, root) { 4 | 5 | this.adjacencyList = {}; 6 | this.vertexNumber = 0; 7 | this.visitedStack = []; 8 | this.found = false; 9 | this.root = root; 10 | 11 | for (let i = 1; i <= n; ++i) { 12 | this.addVertex(i); 13 | } 14 | 15 | } 16 | 17 | addVertex(v) { 18 | this.adjacencyList[v] = []; 19 | this.vertexNumber++; 20 | } 21 | 22 | addEdge(v1, v2) { 23 | this.adjacencyList[v1].push(v2); 24 | this.adjacencyList[v2].push(v1); 25 | } 26 | 27 | reset() { 28 | this.visitedStack = []; 29 | } 30 | 31 | // The graph is traversed with DFS 32 | traverse(a, b, parent) { 33 | 34 | if (a === b) { 35 | this.visitedStack.push(a); 36 | return; 37 | } 38 | 39 | const neighbors = this.adjacencyList[a]; 40 | this.visitedStack.push(a); 41 | 42 | for (let i = 0; i < neighbors.length; ++i) { 43 | 44 | if (neighbors[i] === b) { 45 | this.visitedStack.push(neighbors[i]); 46 | this.found = true; 47 | return true; 48 | } else if (neighbors[i] !== parent) { 49 | 50 | const foundItem = this.traverse(neighbors[i], b, a); 51 | 52 | if (!foundItem) { 53 | this.visitedStack.pop(neighbors[i]); 54 | } else { 55 | return true; 56 | } 57 | 58 | } 59 | 60 | } 61 | 62 | return false; 63 | 64 | } 65 | 66 | findLCA(n1, n2) { 67 | 68 | this.traverse(this.root, n1, this.root); 69 | const path1 = this.getVisitedStack(); 70 | this.reset(); 71 | 72 | this.traverse(this.root, n2, this.root); 73 | const path2 = this.getVisitedStack(); 74 | this.reset(); 75 | 76 | let LCA = null; 77 | for (let i = 0, j = 0; i < path1.length, j < path2.length; ++i, ++j) { 78 | if (path1[i] === path2[j]) { 79 | LCA = path1[i]; 80 | } 81 | } 82 | 83 | // LCA stands for Lowest Common Ancestor 84 | return LCA; 85 | 86 | } 87 | 88 | distanceFromRoot(n1) { 89 | 90 | this.traverse(this.root, n1, this.root); 91 | const distance = this.getVisitedStack().length; 92 | this.reset(); 93 | return distance - 1; 94 | 95 | } 96 | 97 | getVisitedStack() { 98 | return this.visitedStack; 99 | } 100 | 101 | getIsItemFound() { 102 | return this.found; 103 | } 104 | 105 | getRoot() { 106 | return this.root; 107 | } 108 | 109 | } 110 | 111 | function findKittyDistance(pairs, graph) { 112 | 113 | const cache = {}; 114 | let distance = 0; 115 | const exp = Math.pow(10, 9) + 7; 116 | 117 | for (let i = 0; i < pairs.length; ++i) { 118 | 119 | /** 120 | * Distance between two elements in a tree can be calculated as 121 | * dist(root, n1) + dist(root, n2) - 2 * dist(lca(n1, n2)) 122 | */ 123 | let [a, b] = pairs[i].split('~'); 124 | a = parseInt(a); 125 | b = parseInt(b); 126 | 127 | const lca = graph.findLCA(a, b); 128 | 129 | let distanceToLca = 0; 130 | if (lca !== graph.getRoot()) { 131 | distanceToLca = graph.distanceFromRoot(graph.getRoot(), lca); 132 | } 133 | 134 | const rootToA = graph.distanceFromRoot(a); 135 | const rootToB = graph.distanceFromRoot(b); 136 | const distanceAtoB = rootToA + rootToB - 2 * distanceToLca; 137 | distance += a * b * distanceAtoB; 138 | 139 | } 140 | 141 | console.log(distance % exp); 142 | 143 | } 144 | 145 | function findPairs(set) { 146 | 147 | if (set.length === 0) return set; 148 | 149 | let pairs = new Set(); 150 | for (let i = 0; i < set.length; ++i) { 151 | 152 | for (let j = 0; j < set.length; ++j) { 153 | if (i !== j) { 154 | const min = Math.min(set[i], set[j]); 155 | const max = Math.max(set[i], set[j]); 156 | pairs.add(`${min}~${max}`); 157 | } 158 | } 159 | 160 | } 161 | 162 | return new Array(...pairs); 163 | 164 | } 165 | 166 | function processData(input) { 167 | 168 | const date = new Date(); 169 | const data = input.split('\n'); 170 | let [n, q] = data[0].split(' '); 171 | n = parseInt(n); 172 | q = parseInt(q); 173 | 174 | const [root] = data[1].split(' '); 175 | const graph = new Graph(n, parseInt(root)); 176 | 177 | // Build the graph 178 | for (let i = 1; i < n; ++i) { 179 | const [a, b] = data[i].split(' '); 180 | graph.addEdge(parseInt(a), parseInt(b)); 181 | } 182 | 183 | // Calculate the sets 184 | for (let i = n + 1; i < n + (q * 2); i += 2) { 185 | 186 | const currentSet = data[i].split(' ').map(a => parseInt(a)); 187 | let pairsInSet = findPairs(currentSet); 188 | findKittyDistance(pairsInSet, graph); 189 | 190 | } 191 | 192 | console.log(`${new Date().valueOf() - date.valueOf()} milliseconds`); 193 | 194 | } 195 | 196 | const test = `7 3 197 | 1 2 198 | 1 3 199 | 1 4 200 | 3 5 201 | 3 6 202 | 3 7 203 | 2 204 | 2 4 205 | 1 206 | 5 207 | 3 208 | 2 4 5`; 209 | 210 | processData(test); 211 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programming Solutions 2 | 3 | This repository contains my solutions to classic programming problems and problems solved at different online programming websites such as Hacker Rank, Codility, LeetCode and courses 4 | 5 | ## Courses 6 | 7 | This MIT free course covers some of the most common algorithms and data structures. It assumes that you can write code in any programming language. I suggest you to watch the video and before looking at the implementation, try it yourself. Afterwards, you can compare your solution to the teacher's solution and see where you could have improved it. 8 | 9 | https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/lecture-videos/ 10 | 11 | ## Websites where you can study 12 | 13 | - [HackerRank](https://www.hackerrank.com/) 14 | - [Codility](https://www.codility.com/) 15 | - [https://leetcode.com/](https://leetcode.com/) 16 | 17 | Want to try an environment that simulates a real interview ? [Coderpad](https://coderpad.io/) is a tool being used by multiple companies to apply algorithmic challenges to the candidates. Even though, in some ocasions you're not allowed to run your code. 18 | 19 | ## Topics that should be covered 20 | 21 | | Category | Topic Name | Link | 22 | | ------------------ | ------------------- | ---- | 23 | | Search | Binary Search | https://www.geeksforgeeks.org/binary-search/ | 24 | | Sorting | Insertion Sort | https://www.geeksforgeeks.org/insertion-sort/ | 25 | | Sorting | Selection Sort | https://www.geeksforgeeks.org/selection-sort/ | 26 | | Sorting | Radix Sort | https://www.geeksforgeeks.org/radix-sort/ | 27 | | Sorting | Quick Sort | https://www.geeksforgeeks.org/quick-sort/ | 28 | | Sorting | Merge Sort | https://www.geeksforgeeks.org/merge-sort/ | 29 | | Sorting | Heap Sort | https://www.geeksforgeeks.org/heap-sort/ | 30 | | Sorting | Tim Sort | https://www.geeksforgeeks.org/timsort/ | 31 | | Algorithmic Design | Backtracking | https://www.geeksforgeeks.org/backtracking-algorithms/ | 32 | | Algorithmic Design | Divide and Conquer | https://www.geeksforgeeks.org/divide-and-conquer-algorithm-introduction/ | 33 | | Algorithmic Design | Dynamic Programming | https://www.geeksforgeeks.org/dynamic-programming/ | 34 | | Algorithmic Design | Greedy Algorithms | https://www.geeksforgeeks.org/greedy-algorithms/ | 35 | | Algorithmic Design | Recursion | https://www.geeksforgeeks.org/recursion/ | 36 | | Data Structure | Array | https://www.geeksforgeeks.org/array-data-structure/ | 37 | | Data Structure | Stack | https://www.geeksforgeeks.org/stack-data-structure/ | 38 | | Data Structure | Queue | https://www.geeksforgeeks.org/queue-data-structure/ | 39 | | Data Structure | LinkedList | https://www.geeksforgeeks.org/data-structures/linked-list/ | 40 | | Data Structure | Tree | https://www.geeksforgeeks.org/binary-tree-data-structure/ | 41 | | Data Structure | Binary Tree | https://www.geeksforgeeks.org/binary-tree-data-structure/ | 42 | | Data Structure | Binary Search Tree | https://www.geeksforgeeks.org/binary-search-tree-data-structure/ | 43 | | Data Structure | AVL Tree | https://www.geeksforgeeks.org/avl-tree-set-1-insertion/ | 44 | | Data Structure | HashMap | https://www.geeksforgeeks.org/java-util-hashmap-in-java-with-examples/ | 45 | | Data Structure | HashSet | https://www.geeksforgeeks.org/set-in-java/ | 46 | | Data Structure | Disjoint Set | https://www.geeksforgeeks.org/union-find/ | 47 | | Data Structure | Heap | https://www.geeksforgeeks.org/heap-data-structure/ | 48 | | Data Structure | Graph | https://www.geeksforgeeks.org/graph-data-structure-and-algorithms/ | 49 | | Data Structure | Trie | https://www.geeksforgeeks.org/trie-insert-and-search/ | 50 | | Data Structure | Treap | https://www.geeksforgeeks.org/treap-a-randomized-binary-search-tree/ | 51 | | Mathematics | Probability Theory | https://www.geeksforgeeks.org/mathematics-probability/ | 52 | | Mathematics | Combinatorics | https://www.geeksforgeeks.org/mathematics-combinatorics-basics/ | 53 | | Mathematics | Permutations | | 54 | | Mathematics | Summation | | 55 | | Mathematics | GCD | https://www.geeksforgeeks.org/euclidean-algorithms-basic-and-extended/ | 56 | | Graph focused | DFS | https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/ | 57 | | Graph focused | BFS | https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/ | 58 | | Graph focused | Distance | https://www.geeksforgeeks.org/graph-measurements-length-distance-diameter-eccentricity-radius-center/ | 59 | | Graph focused | Connectivity | https://www.geeksforgeeks.org/connectivity-in-a-directed-graph/ | 60 | | Graph focused | Cycle Detection DAG | https://www.geeksforgeeks.org/detect-cycle-in-a-graph/ | 61 | | Graph focused | Cycle Detection | https://www.geeksforgeeks.org/detect-cycle-undirected-graph/ | 62 | | Graph focused | Traversal | https://www.geeksforgeeks.org/algorithms-gq/graph-traversals-gq/ | 63 | | Graph focused | Representation | Maps, Adajcency List, Matrix, Graph Objects | 64 | 65 | ## Extend this list 66 | 67 | If you feel that there's an important topic that should be added, feel free to create pull request. 68 | --------------------------------------------------------------------------------