├── BSTIterator.js ├── Binary Tree Max Path Sum.js ├── Dot Product of spare vector.js ├── Find 1st Different Leaf in BST given two Preorder arrays.js ├── Increasing Triplet Subsequence.js ├── Insert Delete GetRandom O(1).js ├── Insert Interval.js ├── Is Graph Bipartite.js ├── Is-Match-Wildcard.js ├── K Closest Points.js ├── LCA BST.js ├── LCA Binary Tree.js ├── Longest Substring with At Most K Distinct Chars.js ├── Merge Intervals.js ├── Minimum Window Substring.js ├── Multiply Strings.js ├── Palindromic Substring.js ├── README.md ├── Random Pick up Index.js ├── StackImplementationLinkedList.js ├── Sub Array Sum.js ├── Target Sum.js ├── Two Sum.js ├── addBinary.js ├── addOperators.js ├── autocompleteDictionaryTrie.js ├── badVersion.js ├── bestTimeToSellStock.js ├── binaryTreePaths.js ├── cloneGraph.js ├── combinationSum4.js ├── convertBSTToDoubleList.js ├── convertPreorderToBST.js ├── countAndSay.js ├── decodeString.js ├── decodeWays.js ├── divide.js ├── findCelebrity.js ├── findClosestBST.js ├── findDisappearedNumbers.js ├── findKSmallestBST.js ├── findKthLargestInArray.js ├── findMedian.java ├── findShortestPathBFS.js ├── graphValidTree.js ├── groupAnagrams.js ├── groupSumRecursion.js ├── invertTree.js ├── isMatch.js ├── isValidBST.js ├── letterCombinations.js ├── longestArithmeticProgressionSubsequence.js ├── longestCommonSubsequence.js ├── longestIncreasingSubarray.js ├── longestPathInBinaryTree.js ├── maxProductSubarray.js ├── maxSubArrayLen.js ├── maximalSquare.js ├── meetingRooms.js ├── merge k sorted lists-arrays.js ├── mergeTwoIntervals.js ├── minSizeSubarraySum.js ├── minStepToReachTargetKnight.js ├── minesweeper.js ├── minimumRemovalPalindrome.js ├── mostFrequentCharacterInString.js ├── mostFrequentSubtreeSum.js ├── moveZeros.js ├── numIslands.js ├── numberToWords.js ├── oneEditDistance.js ├── powerMode.js ├── previousAndNextPermutation.js ├── printAllPathsIn2DBoard.js ├── printTreeVerticalOp1.js ├── printTreeVerticalOp2.js ├── printTreeVerticalOp3.js ├── randomSubsetOfSizeK.js ├── removeInvalidParenthesis.js ├── reverseList.js ├── runLengthEncoding.js ├── runningMedians.java ├── searchInSortedArray.js ├── serializeAndDeserializeBinaryTree.js ├── sortColors.js ├── squaresOfASortedArray.js ├── strStr.js ├── subset II.js ├── taskScheduler.js ├── treePathsSum.js ├── validPalindrome.js ├── weightedRandomNumbers.js ├── wordBreak.js └── wordDictionaryTrie.js /BSTIterator.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. 3 | 4 | Calling next() will return the next smallest number in the BST. 5 | 6 | Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree. 7 | 8 | https://leetcode.com/problems/binary-search-tree-iterator/description/ 9 | */ 10 | 11 | 12 | // INORDER ITERATOR 13 | function TreeNode(val, left, right) { 14 | this.val = val; 15 | this.left = left || null; 16 | this.right = right || null; 17 | } 18 | 19 | 20 | var BSTIterator = function(root) { 21 | this.stack = []; 22 | this.pushAll(root); 23 | }; 24 | 25 | 26 | // Function to push the most left element into the stack 27 | BSTIterator.prototype.pushAll = function(root) { 28 | while(root) { 29 | this.stack.push(root); 30 | root = root.left; 31 | } 32 | }; 33 | 34 | 35 | /** 36 | * @this BSTIterator 37 | * @returns {boolean} - whether we have a next smallest number 38 | */ 39 | BSTIterator.prototype.hasNext = function() { 40 | return !(this.stack.length === 0); 41 | }; 42 | 43 | /** 44 | * @this BSTIterator 45 | * @returns {number} - the next smallest number 46 | */ 47 | BSTIterator.prototype.next = function() { 48 | let node = this.stack.pop(); 49 | // Insert right nodes in our stack considering also the left nodes 50 | this.pushAll(node.right); 51 | return node.val; 52 | }; 53 | 54 | root = new TreeNode(8, new TreeNode(3, new TreeNode(1), new TreeNode(6, new TreeNode(4), new TreeNode(7))), new TreeNode(10, null, new TreeNode(14, new TreeNode(13)))); 55 | 56 | 57 | /** 58 | * Your BSTIterator will be called like this: 59 | **/ 60 | var i = new BSTIterator(root); 61 | a = []; 62 | while(i.hasNext()) { 63 | a.push(i.next()); 64 | } 65 | console.log(a); 66 | 67 | 68 | /** Including All **/ 69 | 70 | function TreeNode(val, left, right) { 71 | this.val = val; 72 | this.left = left || null; 73 | this.right = right || null; 74 | } 75 | 76 | 77 | var BSTIterator = function(root) { 78 | this.stack = []; 79 | this.pushAll(root); 80 | }; 81 | 82 | 83 | // Function to push the most left element into the stack 84 | BSTIterator.prototype.pushAll = function(root) { 85 | while(root) { 86 | this.stack.push(root); 87 | root = root.left; 88 | } 89 | }; 90 | 91 | 92 | /** 93 | * @this BSTIterator 94 | * @returns {boolean} - whether we have a next smallest number 95 | */ 96 | BSTIterator.prototype.hasNext = function() { 97 | return !(this.stack.length === 0); 98 | }; 99 | 100 | /** 101 | * @this BSTIterator 102 | * @returns {number} - the next smallest number 103 | */ 104 | BSTIterator.prototype.next = function() { 105 | let node = this.stack.pop(); 106 | // Insert right nodes in our stack considering also the left nodes 107 | this.pushAll(node.right); 108 | return node.val; 109 | }; 110 | 111 | BSTIterator.prototype.all = function() { 112 | let result = []; 113 | while(this.hasNext()) { 114 | result.push(this.next()); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Binary Tree Max Path Sum.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Given a non-empty binary tree, find the maximum path sum. 4 | 5 | For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. 6 | 7 | Example 1: 8 | 9 | Input: [1,2,3] 10 | 11 | 1 12 | / \ 13 | 2 3 14 | 15 | Output: 6 16 | Example 2: 17 | 18 | Input: [-10,9,20,null,null,15,7] 19 | 20 | -10 21 | / \ 22 | 9 20 23 | / \ 24 | 15 7 25 | 26 | Output: 42 27 | 28 | https://leetcode.com/problems/binary-tree-maximum-path-sum/ 29 | 30 | */ 31 | 32 | // Opción 1 33 | 34 | var maxPathSum = function(root) { 35 | // Result 36 | let result = {val: -10e5}; 37 | findMaxPathSum(root, result); 38 | return result.val; 39 | }; 40 | 41 | function findMaxPathSum(node, result) { 42 | if(!node) { 43 | return 0; 44 | } 45 | 46 | let left = findMaxPathSum(node.left, result); 47 | let right = findMaxPathSum(node.right, result); 48 | 49 | // Get max of single node, should include at lear one child 50 | // Could be only the single root node or root node + max one children 51 | let max_single = Math.max(Math.max(left, right) + node.val, node.val); 52 | 53 | // Max top is the sum 54 | // The max could the the one subtree that includes the root node also 55 | let max_top = Math.max(max_single, left + right + node.val); 56 | 57 | // Update the result 58 | // The new max is the prev result or our max of single node 59 | result.val = Math.max(result.val, max_top); 60 | 61 | // We need to return the max of each subtree so we can keep compute 62 | // This will be a repetitive process for all root nodes 63 | return max_single; 64 | } 65 | 66 | // Opción 2 67 | 68 | let max = Number.MIN_SAFE_INTEGER; 69 | var maxPathSum = function(root) { 70 | dfs(root); 71 | return max; 72 | } 73 | function dfs(root) { 74 | if (!root) return 0; 75 | let left = Math.max(0, dfs(root.left)); 76 | let right = Math.max(0, dfs(root.right)); 77 | max = Math.max(max, left + right + root.val); 78 | return Math.max(left, right) + root.val; 79 | } -------------------------------------------------------------------------------- /Dot Product of spare vector.js: -------------------------------------------------------------------------------- 1 | /* 2 | Dot Product of spare vector: 3 | 4 | a0 b1 5 | a1 b2 6 | a2 X b3 = a0xb0 + a1xb1 + a2xb2 ..... + anxbn 7 | a3 b4 8 | a4 b5 9 | an bn 10 | 11 | https://leetcode.com/discuss/interview-question/124823/dot-product-of-sparse-vector/ 12 | */ 13 | 14 | var dotProduct = function(a, b) { 15 | let hashA = {}; 16 | let hashB = {}; 17 | let result = 0; 18 | 19 | if(a.length && !b.length) { 20 | return a; 21 | } 22 | 23 | if(b.length && !a.length) { 24 | return b; 25 | } 26 | 27 | for(let i = 0; i < Math.max(a.length, b.length); i++) { 28 | if(a[i] && a[i] !== 0) hashA[i] = a[i]; 29 | if(b[i] && b[i] !== 0) hashB[i] = b[i]; 30 | } 31 | 32 | for(key in hashA) { 33 | if(key in hashB) { 34 | result += hashA[key] * hashB[key]; 35 | } 36 | } 37 | 38 | return result; 39 | } 40 | 41 | a = [1,4,6,8,9,6]; 42 | b = [2,8,2,4,3]; 43 | console.log(dotProduct(a, b)); -------------------------------------------------------------------------------- /Find 1st Different Leaf in BST given two Preorder arrays.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given two pre-order traversal arrays of two binary search tree respectively, find first pair of non-matching leaves. 3 | Follow Up: If they are general binary trees instead of BSTs, could you solve it? give out your reason. 4 | 5 | For the first question, I was thinking to construct two BSTs from pre-order traversal then do a leaf-level comparison. Any better solutions are welcome. 6 | 7 | https://www.careercup.com/question?id=5692379756494848 8 | */ 9 | 10 | function TreeNode(val, left, right) { 11 | this.val = val; 12 | this.left = left || null; 13 | this.right = right || null; 14 | } 15 | 16 | // http://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/ 17 | function findNotMatchingLeaf(preorder1, preorder2) { 18 | index = 0; 19 | let tree1 = constructBSTFromPreorder(preorder1); 20 | index = 0; 21 | let tree2 = constructBSTFromPreorder(preorder2); 22 | 23 | let leaves1 = []; 24 | let leaves2 = []; 25 | let result = []; 26 | 27 | preorder(tree1, leaves1); 28 | preorder(tree2, leaves2); 29 | 30 | // Compare the first pair 31 | for(let i = 0; i < Math.min(leaves1.length, leaves2.length); i++) { 32 | if(leaves1[i] !== leaves2[i]) { 33 | result[0] = leaves1[i]; 34 | result[1] = leaves2[i]; 35 | return result; 36 | } 37 | } 38 | return result; 39 | } 40 | 41 | // O(N) 42 | function constructBSTFromPreorder(array) { 43 | return constructTreeUtil(array, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); 44 | } 45 | 46 | function constructTreeUtil(array, min, max) { 47 | // Base Case 48 | if(index >= array.length) { 49 | return null; 50 | } 51 | 52 | if(array[index] <= min || array[index] >= max) { 53 | return null; 54 | } 55 | 56 | let root = new TreeNode(array[index++]); 57 | root.left = constructTreeUtil(array, min, root.val); 58 | root.right = constructTreeUtil(array, root.val, max); 59 | 60 | return root; 61 | } 62 | 63 | function preorder(node, array) { 64 | if(!node) { 65 | return; 66 | } 67 | array.push(node.val); 68 | preorder(node.left, array); 69 | preorder(node.right, array); 70 | } 71 | 72 | preorder1 = [5, 2, 10, 11, 7]; 73 | preorder2 = [5, 2, 10, 11]; 74 | console.log(findNotMatchingLeaf(preorder1, preorder2)); -------------------------------------------------------------------------------- /Increasing Triplet Subsequence.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array. 3 | 4 | Formally the function should: 5 | 6 | Return true if there exists i, j, k 7 | such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. 8 | Note: Your algorithm should run in O(n) time complexity and O(1) space complexity. 9 | 10 | Example 1: 11 | 12 | Input: [1,2,3,4,5] 13 | Output: true 14 | Example 2: 15 | 16 | Input: [5,4,3,2,1] 17 | Output: false 18 | 19 | https://leetcode.com/problems/increasing-triplet-subsequence/ 20 | */ 21 | 22 | // Start with the maximum numbers for the first and second element. Then: 23 | // (1) Find the first smallest number in the 3 subsequence 24 | // (2) Find the second one greater than the first element, reset the first one if it's smaller 25 | var increasingTriplet = function(nums) { 26 | let min = Number.MAX_SAFE_INTEGER; 27 | let secondMin = Number.MAX_SAFE_INTEGER; 28 | 29 | for(let i = 0; i < nums.length; i++) { 30 | if(nums[i] <= min) { 31 | min = nums[i]; 32 | } else if(nums[i] <= secondMin) { 33 | secondMin = nums[i]; 34 | } else { 35 | return true; 36 | } 37 | } 38 | 39 | return false; 40 | }; -------------------------------------------------------------------------------- /Insert Delete GetRandom O(1).js: -------------------------------------------------------------------------------- 1 | /* 2 | Design a data structure that supports all following operations in average O(1) time. 3 | 4 | insert(val): Inserts an item val to the set if not already present. 5 | remove(val): Removes an item val from the set if present. 6 | getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned. 7 | Example: 8 | 9 | // Init an empty set. 10 | RandomizedSet randomSet = new RandomizedSet(); 11 | 12 | // Inserts 1 to the set. Returns true as 1 was inserted successfully. 13 | randomSet.insert(1); 14 | 15 | // Returns false as 2 does not exist in the set. 16 | randomSet.remove(2); 17 | 18 | // Inserts 2 to the set, returns true. Set now contains [1,2]. 19 | randomSet.insert(2); 20 | 21 | // getRandom should return either 1 or 2 randomly. 22 | randomSet.getRandom(); 23 | 24 | // Removes 1 from the set, returns true. Set now contains [2]. 25 | randomSet.remove(1); 26 | 27 | // 2 was already in the set, so return false. 28 | randomSet.insert(2); 29 | 30 | // Since 2 is the only number in the set, getRandom always return 2. 31 | randomSet.getRandom(); 32 | 33 | https://leetcode.com/problems/insert-delete-getrandom-o1/ 34 | */ 35 | 36 | /** 37 | * Initialize your data structure here. 38 | */ 39 | var RandomizedSet = function() { 40 | this.nums = []; 41 | this.map = {}; 42 | }; 43 | 44 | /** 45 | * Inserts a value to the set. Returns true if the set did not already contain the specified element. 46 | * @param {number} val 47 | * @return {boolean} 48 | */ 49 | RandomizedSet.prototype.insert = function(val) { 50 | if(val in this.map) return false; 51 | // If the element is not present 52 | this.map[val] = this.nums.length; 53 | this.nums.push(val); 54 | return true; 55 | }; 56 | 57 | /** 58 | * Removes a value from the set. Returns true if the set contained the specified element. 59 | * @param {number} val 60 | * @return {boolean} 61 | */ 62 | RandomizedSet.prototype.remove = function(val) { 63 | if(!(val in this.map)) return false; 64 | 65 | let index = this.map[val]; 66 | 67 | // Swap the index of the element we want to remove with the last element, as we want to make it O(1), shifting will be 68 | // faster than just removing in any index 69 | // shift the removed element to the last position instead of removing 70 | let lastElemet = this.nums[this.nums.length - 1]; 71 | let tmp = this.nums[index]; 72 | this.nums[index] = lastElemet; 73 | this.nums[this.nums.length - 1] = tmp; 74 | 75 | // Update the map with the value of the last element 76 | this.map[lastElemet] = index; 77 | 78 | // delete from the map 79 | delete this.map[val]; 80 | // delete from the array the last element as we know is the want to remove, we swapped to the final of the array 81 | this.nums.pop(); 82 | return true; 83 | }; 84 | 85 | /** 86 | * Get a random element from the set. 87 | * @return {number} 88 | */ 89 | RandomizedSet.prototype.getRandom = function() { 90 | let index = Math.floor(Math.random() * this.nums.length); 91 | return this.nums[index]; 92 | }; 93 | 94 | /** 95 | * Your RandomizedSet object will be instantiated and called as such: 96 | * var obj = Object.create(RandomizedSet).createNew() 97 | * var param_1 = obj.insert(val) 98 | * var param_2 = obj.remove(val) 99 | * var param_3 = obj.getRandom() 100 | */ 101 | 102 | // Init an empty set. 103 | randomSet = new RandomizedSet(); 104 | console.log(randomSet.insert(0)); 105 | console.log(randomSet.insert(1)); 106 | console.log(randomSet.remove(0)); 107 | console.log(randomSet.insert(2)); 108 | console.log(randomSet.remove(0)); 109 | console.log(randomSet.getRandom()); 110 | -------------------------------------------------------------------------------- /Insert Interval.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). 3 | 4 | You may assume that the intervals were initially sorted according to their start times. 5 | 6 | Example 1: 7 | 8 | Input: intervals = [[1,3],[6,9]], newInterval = [2,5] 9 | Output: [[1,5],[6,9]] 10 | Example 2: 11 | 12 | Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 13 | Output: [[1,2],[3,10],[12,16]] 14 | Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. 15 | 16 | https://leetcode.com/problems/insert-interval/ 17 | */ 18 | 19 | function Interval(start, end) { 20 | this.start = start; 21 | this.end = end; 22 | } 23 | 24 | var insert = function(intervals, newInterval) { 25 | let result = []; 26 | let i = 0; 27 | 28 | // Here we handle all of the non overlapping cases that we are sure 29 | while(i < intervals.length && intervals[i].end < newInterval.start) { 30 | result.push(intervals[i++]); 31 | } 32 | 33 | while(i < intervals.length && intervals[i].start <= newInterval.end) { 34 | newInterval.start = Math.min(intervals[i].start, newInterval.start); 35 | newInterval.end = Math.max(intervals[i].end, newInterval.end); 36 | i++; 37 | } 38 | 39 | //Add the result of the overlapping 40 | result.push(newInterval); 41 | 42 | // Add the rest of the cases we don´t match the conditions above 43 | while(i < intervals.length) { 44 | result.push(intervals[i++]); 45 | } 46 | 47 | return result; 48 | }; 49 | 50 | newInterval = new Interval(2,5); 51 | intervals = [new Interval(1,3), new Interval(6,9)]; 52 | console.log(insert(intervals, newInterval)); -------------------------------------------------------------------------------- /Is Graph Bipartite.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an undirected graph, return true if and only if it is bipartite. 3 | 4 | Recall that a graph is bipartite if we can split it's set of nodes into two independent subsets A and B such that every edge in the graph has one node in A and another node in B. 5 | 6 | The graph is given in the following form: graph[i] is a list of indexes j for which the edge between nodes i and j exists. Each node is an integer between 0 and graph.length - 1. There are no self edges or parallel edges: graph[i] does not contain i, and it doesn't contain any element twice. 7 | 8 | Example 1: 9 | Input: [[1,3], [0,2], [1,3], [0,2]] 10 | Output: true 11 | Explanation: 12 | The graph looks like this: 13 | 0----1 14 | | | 15 | | | 16 | 3----2 17 | We can divide the vertices into two groups: {0, 2} and {1, 3}. 18 | Example 2: 19 | Input: [[1,2,3], [0,2], [0,1,3], [0,2]] 20 | Output: false 21 | Explanation: 22 | The graph looks like this: 23 | 0----1 24 | | \ | 25 | | \ | 26 | 3----2 27 | We cannot find a way to divide the set of nodes into two independent subsets. 28 | 29 | // https://leetcode.com/problems/is-graph-bipartite/discuss/161001/Java-Graph-Coloring-BFS-with-Explanation 30 | */ 31 | 32 | // DFS 33 | // Time complexity: O(V+E) 34 | // Space complexity: O(V) 35 | var isBipartite = function(graph) { 36 | let n = graph.length; 37 | let colors = new Array(n).fill(0); 38 | 39 | // Check all nodes 40 | for (let i = 0; i < n; i++) { 41 | if (colors[i] == 0 && !dfs(graph, colors, i, 1)) { 42 | return false; 43 | } 44 | } 45 | return true; 46 | } 47 | 48 | function dfs(graph, colors, node, color) { 49 | // Mark node as visited 50 | colors[node] = color; 51 | for(let i = 0; i < graph[node].length; i++) { 52 | let next = graph[node][i]; 53 | // if the next node has the same color, then return false 54 | if (colors[next] == colors[node]) { 55 | return false; 56 | } 57 | // if the next node hasn't been dyed, check it can be successfully 58 | if (colors[next] == 0 && !dfs(graph, colors, next, -color)) { 59 | return false; 60 | } 61 | } 62 | return true; 63 | } 64 | 65 | // BFS 66 | // Time complexity: O(V+E) 67 | // Space complexity: O(V) 68 | var isBipartite = function(graph) { 69 | let n = graph.length; 70 | let colors = new Array(n).fill(0); 71 | 72 | let queue = []; 73 | 74 | for(let i = 0; i < n; i++) { 75 | // If it's not visited 76 | if(colors[i] === 0) { 77 | queue.push(i); 78 | colors[i] = 1; 79 | 80 | while(queue.length) { 81 | let node = queue.shift(); 82 | let nextColor = -colors[node]; 83 | for(let i = 0; i < graph[node].length; i++) { 84 | let next = graph[node][i]; 85 | // If it's not visited 86 | if(colors[next] === 0) { 87 | queue.push(next); 88 | colors[next] = nextColor; 89 | } else if(colors[next] === colors[node]) { 90 | // If we have the same color as the prev node, it's not a bipartite graph 91 | return false; 92 | } 93 | } 94 | } 95 | } 96 | } 97 | return true; 98 | } 99 | 100 | graph = [[1,3], [0,2], [1,3], [0,2]]; // true 101 | //graph = [[1,2,3], [0,2], [0,1,3], [0,2]]; // false 102 | console.log(isBipartite(graph)); -------------------------------------------------------------------------------- /Is-Match-Wildcard.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*'. 3 | 4 | '?' Matches any single character. 5 | '*' Matches any sequence of characters (including the empty sequence). 6 | The matching should cover the entire input string (not partial). 7 | 8 | Note: 9 | 10 | s could be empty and contains only lowercase letters a-z. 11 | p could be empty and contains only lowercase letters a-z, and characters like ? or *. 12 | 13 | https://leetcode.com/problems/wildcard-matching/description/ 14 | */ 15 | 16 | var isMatch = function(s, p) { 17 | let memo = [] 18 | for(let i = 0; i < s.length+1; i++) { 19 | memo[i] = new Array(p.length+1); 20 | } 21 | return dp(s, p, 0, 0, memo); 22 | }; 23 | 24 | function dp(s, p, i, j, memo) { 25 | if(memo[i][j]) { 26 | return memo[i][j]; 27 | } 28 | 29 | let result = false; 30 | // Check last char of p, if it's '*' return true, we have checked all the chars at this point 31 | if(j === p.length-1 && p[j] === "*") { 32 | result = true; 33 | } else { 34 | // If we complete the check for j 35 | if(j === p.length) { 36 | // If we still have chars in "s" means we were not able to match 37 | return i === s.length; 38 | } 39 | if(p[j] === "*") { 40 | // if "*" is empty sequence(blank space) check dp(s,p,i, j+1, memo) 41 | //otherwise check dp(s,p,i+1,j, memo) 42 | result = dp(s,p,i,j+1,memo) || (i < s.length && dp(s,p, i+1, j, memo)) 43 | } else if (i < s.length && (s[i] === p[j] || p[j] === '?')) { 44 | result = dp(s,p, i+1, j+1, memo); 45 | } 46 | } 47 | memo[i][j] = result; 48 | return result; 49 | } 50 | 51 | 52 | s = "aab"; 53 | p = "c*a*b"; 54 | console.log(isMatch(s,p)); -------------------------------------------------------------------------------- /K Closest Points.js: -------------------------------------------------------------------------------- 1 | /* 2 | Example 1: 3 | 4 | Input: points = [[1,3],[-2,2]], K = 1 5 | Output: [[-2,2]] 6 | Explanation: 7 | The distance between (1, 3) and the origin is sqrt(10). 8 | The distance between (-2, 2) and the origin is sqrt(8). 9 | Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin. 10 | We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]]. 11 | Example 2: 12 | 13 | Input: points = [[3,3],[5,-1],[-2,4]], K = 2 14 | Output: [[3,3],[-2,4]] 15 | (The answer [[-2,4],[3,3]] would also be accepted.) 16 | 17 | https://leetcode.com/problems/k-closest-points-to-origin/ 18 | */ 19 | // https://www.cs.bgu.ac.il/~ds122/wiki.files/Presentation09.pdf 20 | // Reference: https://en.wikipedia.org/wiki/Euclidean_distance 21 | // https://www.youtube.com/watch?v=eaYX0Ee0Kcg 22 | // O(N log N) 23 | 24 | // NOTE: We can user a max heap too (max heap has the root as greater element) 25 | var kClosest = function(points, K) { 26 | 27 | if(!points.length || !K) { 28 | return []; 29 | } 30 | 31 | let origin = [0,0]; 32 | let array = []; 33 | let result = []; 34 | for(let i = 0; i < points.length; i++) { 35 | array.push({coordinate: points[i], distance: getEuclideanDistance(points[i], origin)}); 36 | } 37 | 38 | // Custom sort - comparator using distance for sorting 39 | array.sort((a,b) => (a.distance - b.distance)); 40 | 41 | // Create the array result 42 | for(let i = 0; i < K; i++) { 43 | result.push(array[i].coordinate); 44 | } 45 | 46 | return result; 47 | }; 48 | 49 | // Euclidean distance 50 | // Formula = Math.sqrt((a1 - b1)^2 + (a2 - b2)^2 + .... + (an - b2)) 51 | function getEuclideanDistance(a, b) { 52 | return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2)); 53 | } -------------------------------------------------------------------------------- /LCA BST.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. 3 | 4 | According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).” 5 | 6 | Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] 7 | 8 | _______6______ 9 | / \ 10 | ___2__ ___8__ 11 | / \ / \ 12 | 0 _4 7 9 13 | / \ 14 | 3 5 15 | 16 | https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/ 17 | 18 | https://www.youtube.com/watch?v=TIoCCStdiFo 19 | 20 | */ 21 | 22 | // Time O(h) with O(h) space for call stack 23 | var lowestCommonAncestor = function(root, p, q) { 24 | // Base Case 25 | if(!root) return; 26 | 27 | /* if p and q are greater than root, LCA is in 28 | the right side*/ 29 | if(root.val < p.val && root.val < q.val) { 30 | return lowestCommonAncestor(root.right, p, q); 31 | } 32 | 33 | /* if p and q are smaller than root, LCA is in 34 | the left side*/ 35 | if(root.val > p.val && root.val > q.val) { 36 | return lowestCommonAncestor(root.left, p, q); 37 | } 38 | return root; 39 | } 40 | 41 | // Time O(h) with O(h) space for call stack 42 | var lowestCommonAncestor = function(root, p, q) { 43 | // Base Case 44 | if(!root) return; 45 | 46 | if(root.val > Math.max(p.val, q.val)) { 47 | return lowestCommonAncestor(root.left, p, q); 48 | } else if(root.val < Math.min(p.val, q.val)) { 49 | return lowestCommonAncestor(root.right, p, q); 50 | } else{ 51 | return root; 52 | } 53 | }; 54 | 55 | // Time O(h) with O(1) 56 | // Iterative 57 | var lowestCommonAncestor = function(root, p, q) { 58 | while(root) { 59 | if(root.val < p.val && root.val < q.val) { 60 | root = root.right; 61 | } else if(root.val > p.val && root.val > q.val) { 62 | root = root.left; 63 | } else { 64 | break; 65 | } 66 | } 67 | return root; 68 | }; 69 | 70 | 71 | /* 72 | 5 73 | 3 7 74 | 2 4 6 8 75 | */ 76 | tree = new TreeNode(5,new TreeNode(3, new TreeNode(2, new TreeNode(4))), new TreeNode(7, new TreeNode(6), new TreeNode(8))); 77 | n1 = 2; 78 | n2 = 4; //Output 3 79 | console.log(LCABST(tree,n1,n2)); -------------------------------------------------------------------------------- /LCA Binary Tree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. 3 | 4 | According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between 5 | two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).” 6 | 7 | _______3______ 8 | / \ 9 | ___5__ ___1__ 10 | / \ / \ 11 | 6 _2 0 8 12 | / \ 13 | 7 4 14 | 15 | For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5 16 | since a node can be a descendant of itself according to the LCA definition. 17 | 18 | https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ 19 | https://www.youtube.com/watch?v=13m9ZCB8gjw 20 | */ 21 | 22 | // O(N) time and O(N) space 23 | 24 | var lowestCommonAncestor = function(root, p, q) { 25 | 26 | if(p === null || q === null) { 27 | return -1; 28 | } 29 | 30 | let path1 = []; 31 | let path2 = []; 32 | 33 | let isFoundPath1 = findPath(root, p, path1); 34 | let isFoundPath2 = findPath(root, q, path2); 35 | 36 | // Check if both paths were found, if not, return error 37 | if(!isFoundPath1 || !isFoundPath2) { 38 | return -1; 39 | } 40 | 41 | // If we reach this point, it means we found both nodes 42 | // Let's find the ancestor comparing paths one by one 43 | let i = 0; 44 | while((path1[i] && path2[i]) && (path1[i].val === path2[i].val)) { 45 | i++; 46 | } 47 | 48 | // Return once we find a different element, that's the ancestor 49 | // We could use any of those arrays 50 | return path1[i-1]; 51 | }; 52 | 53 | // Find path from root to specific node 54 | function findPath(root, node, arr) { 55 | // Base case 56 | if(!root) { 57 | return; 58 | } 59 | 60 | arr.push(root); 61 | if(root.val === node.val) { 62 | return true; 63 | } 64 | 65 | // Look in both sides 66 | let wasFound = findPath(root.left, node, arr) || findPath(root.right, node, arr); 67 | if(wasFound) { 68 | return true; 69 | } 70 | 71 | // Node was not found, remove from array the element and keep recursion 72 | arr.pop(); 73 | return false; 74 | } 75 | 76 | // O(N) time and O(1) space 77 | 78 | var lowestCommonAncestor = function(root, p, q) { 79 | // Base case 80 | if(root === null) { 81 | return null; 82 | } 83 | 84 | // If we found a node while traversing, return it 85 | if(root.val === p.val || root.val === q.val) { 86 | return root; 87 | } 88 | 89 | let left = lowestCommonAncestor(root.left, p, q); 90 | let right = lowestCommonAncestor(root.right, p, q); 91 | 92 | // If we have nodes from both, left and right, means that we 93 | // have found the lowest common ancestor 94 | // Means this is the LCA, return the current node 95 | if(left && right) { 96 | return root; 97 | } 98 | 99 | // If we reach this point it means that we have null in left or right node 100 | // so let's return to the parent the one is not null 101 | return left ? left : right; 102 | }; 103 | 104 | 105 | var lowestCommonAncestor = function(root, p, q) { 106 | if(root === null) return null; 107 | if(root === p || root === q) return root; 108 | let left = lowestCommonAncestor(root.left, p,q); 109 | let right = lowestCommonAncestor(root.right, p,q); 110 | if(left !== null && right !== null) return root; 111 | if(left === null && right === null) return null; 112 | return left !== null ? left : right; 113 | }; -------------------------------------------------------------------------------- /Longest Substring with At Most K Distinct Chars.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string, find the length of the longest substring T that contains at most k distinct characteres. 3 | For example, Given s = "eceba" and k = 2 4 | T is "ece" which length is 3 5 | 6 | https://www.youtube.com/watch?v=RHFrVNmlyA8 7 | https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/ 8 | 9 | Time Complexity O(N) 10 | Space Complexity O(N) 11 | */ 12 | var lengthOfLongestSubstringKDistinct = function (str, k) { 13 | let hash = {}; 14 | let result = 0; 15 | 16 | let start = 0; 17 | let end = 0; 18 | 19 | while (end < str.length) { 20 | let c = str[end]; 21 | if (!(c in hash)) { 22 | hash[c] = 0; 23 | } 24 | hash[c]++; 25 | 26 | if (Object.keys(hash).length <= k) { 27 | result = Math.max(result, end - start + 1); 28 | } else { 29 | // If we have rebased the limit, remove the most left element 30 | while (Object.keys(hash).length > k) { 31 | let l = str[start]; 32 | let count = hash[l]; 33 | if (count === 1) { 34 | delete hash[l]; 35 | } else { 36 | hash[l]--; 37 | } 38 | start++; 39 | } 40 | } 41 | end++; 42 | } 43 | return result; 44 | }; 45 | 46 | str = "karappa"; 47 | k = 2; // appa - result = 4 48 | k = 3; // arappa - result = 6 49 | console.log(lengthOfLongestSubstringKDistinct(str, k)); 50 | 51 | // Time O(N) 52 | // Space O(N) 53 | // https://www.youtube.com/watch?v=8AQra0p_HmI 54 | // https://www.programcreek.com/2013/02/longest-substring-which-contains-2-unique-characters/ 55 | var lengthOfLongestSubstringKDistinct = function (str, k) { 56 | let hash = {}; 57 | let result = 0; 58 | let start = 0; 59 | 60 | for (let i = 0; i < str.length; i++) { 61 | let c = str[i]; 62 | if (c in hash) { 63 | hash[c]++; 64 | } else { 65 | hash[c] = 1; 66 | } 67 | 68 | if (Object.keys(hash).length <= k) { 69 | result = Math.max(result, i - start + 1); 70 | } else { 71 | // If we have rebased the limit, remove the most left element 72 | while (Object.keys(hash).length > k) { 73 | let l = str[start]; 74 | let count = hash[l]; 75 | if (count === 1) { 76 | delete hash[l]; 77 | } else { 78 | hash[l]--; 79 | } 80 | start++; 81 | } 82 | } 83 | } 84 | return result; 85 | }; 86 | -------------------------------------------------------------------------------- /Merge Intervals.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a collection of intervals, merge all overlapping intervals. 3 | 4 | Example 1: 5 | 6 | Input: [[1,3],[2,6],[8,10],[15,18]] 7 | Output: [[1,6],[8,10],[15,18]] 8 | Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. 9 | Example 2: 10 | 11 | Input: [[1,4],[4,5]] 12 | Output: [[1,5]] 13 | Explanation: Intervals [1,4] and [4,5] are considered overlapping. 14 | 15 | https://leetcode.com/problems/merge-intervals/ 16 | */ 17 | 18 | function Interval(start, end) { 19 | this.start = start; 20 | this.end = end; 21 | } 22 | 23 | var merge = function(intervals) { 24 | let result = []; 25 | 26 | if(!intervals || !intervals.length) { 27 | return []; 28 | } 29 | 30 | // Sort using start time as point of sorting 31 | // Use a comparator 32 | intervals = intervals.sort((a,b) => a.start - b.start); 33 | 34 | // Insert first element 35 | let pre = intervals[0]; 36 | for(let i = 0; i < intervals.length; i++){ 37 | let curr = intervals[i]; 38 | // There´s no overlap 39 | if(curr.start > pre.end) { 40 | result.push(pre); 41 | pre = curr; 42 | } else{ 43 | let merged = new Interval(pre.start, Math.max(pre.end, curr.end)); 44 | pre = merged; 45 | } 46 | } 47 | // The missing one 48 | result.push(pre); 49 | 50 | return result; 51 | }; 52 | 53 | // Time O(N Long N) 54 | function Interval(start, end) { 55 | this.start = start; 56 | this.end = end; 57 | } 58 | 59 | var merge = function(intervals) { 60 | let result = []; 61 | let index = null; 62 | 63 | if(!intervals || !intervals.length) { 64 | return []; 65 | } 66 | 67 | // Sort using start time as point of sorting 68 | // Use a comparator 69 | intervals = intervals.sort((a,b) => a.start - b.start); 70 | 71 | // Index is used to control the index of our result array, regardless the current interval array 72 | for(let i = 0; i < intervals.length; i++) { 73 | if(!result.length) { 74 | result.push(intervals[i]); 75 | index = 0; 76 | } else if(intervals[i].start == result[index].end || intervals[i].start < result[index].end){ 77 | // Here it means we have an overlap 78 | let tmp = result.pop(); 79 | let start = Math.min(intervals[i].start, tmp.start); 80 | let end = Math.max(intervals[i].end, tmp.end); 81 | result.push(new Interval(start, end)); 82 | } else { 83 | // No overlap 84 | result.push(intervals[i]); 85 | index++; 86 | } 87 | } 88 | return result; 89 | }; 90 | 91 | // intervals = [new Interval(1,4), new Interval(0,2), new Interval(3,5)]; // [0,5] 92 | // intervals = [new Interval(1,3), new Interval(2,6), new Interval(8,10), new Interval(15,18)]; //[[1,6],[8,10],[15,18]] 93 | intervals = [new Interval(1,4), new Interval(4,5)]; //[[1,5]] 94 | console.log(merge(intervals)); -------------------------------------------------------------------------------- /Minimum Window Substring.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). 3 | 4 | Example: 5 | 6 | Input: S = "ADOBECODEBANC", T = "ABC" 7 | Output: "BANC" 8 | Note: 9 | 10 | If there is no such window in S that covers all characters in T, return the empty string "". 11 | If there is such window, you are guaranteed that there will always be only one unique minimum window in S. 12 | 13 | https://leetcode.com/problems/minimum-window-substring/ 14 | 15 | */ 16 | 17 | /** 18 | * @param {string} s 19 | * @param {string} t 20 | * @return {string} 21 | */ 22 | 23 | /* 24 | ADOBECODEBANC 25 | BANC 26 | [ADOBEC]ODEBANC, MIN WINDOW = 6 27 | A[DOBECODEBA]NC, MIN WINDOW = 6 28 | ADOBE[CODEBA]NC, MIN WINDOW = 6 29 | ADOBECODE[BANC], MIN WINDOW = 4 30 | 31 | // Sliding window technique 32 | 1. Cuando la window está calificada para tener el resultado, movemos el head 33 | 2. Cuando no, movemos la cola del window 34 | */ 35 | var minWindow = function (s, t) { 36 | let map = {}; 37 | // We only care about the frequency on T 38 | for (const char of t) { 39 | map[char] = (map[char] || 0) + 1; 40 | } 41 | 42 | let start = 0; 43 | let end = 0; 44 | let minLength = Infinity; 45 | let minStart = 0; 46 | let count = t.length; 47 | 48 | while (end < s.length) { 49 | let current = s[end]; 50 | // Check if the element is in the map, if yes, decrement the target 51 | if (current in map) { 52 | // As long as we have elements to decrese we deduct 53 | if (map[current] > 0) { 54 | count--; 55 | } 56 | // Update the map always, we can have numbers < 0 if our window does not have 57 | // a number in the "t" string 58 | map[current]--; 59 | } 60 | 61 | // Elegible window for a result 62 | while (count === 0) { 63 | // Try to get the min result 64 | if (end - start + 1 < minLength) { 65 | minLength = end - start + 1; 66 | // Track where the min window starts 67 | minStart = start; 68 | } 69 | // Move the window 70 | let l = s[start]; 71 | // We only care about those being tracked 72 | // We need to find them again later 73 | if (map[l] >= 0) { 74 | count++; 75 | } 76 | map[l]++; 77 | start++; 78 | } 79 | // Increase the end window 80 | end++; 81 | } 82 | return minLength === Infinity 83 | ? "" 84 | : s.substring(minStart, minStart + minLength); 85 | }; 86 | -------------------------------------------------------------------------------- /Multiply Strings.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. 3 | 4 | Example 1: 5 | 6 | Input: num1 = "2", num2 = "3" 7 | Output: "6" 8 | Example 2: 9 | 10 | Input: num1 = "123", num2 = "456" 11 | Output: "56088" 12 | Note: 13 | 14 | The length of both num1 and num2 is < 110. 15 | Both num1 and num2 contain only digits 0-9. 16 | Both num1 and num2 do not contain any leading zero, except the number 0 itself. 17 | You must not use any built-in BigInteger library or convert the inputs to integerdirectly. 18 | 19 | https://leetcode.com/problems/multiply-strings/ 20 | https://leetcode.com/problems/multiply-strings/discuss/17605/Easiest-JAVA-Solution-with-Graph-Explanation 21 | */ 22 | 23 | var multiply = function(num1, num2) { 24 | let m = num1.length; 25 | let n = num2.length; 26 | let posNum = new Array(m + n).fill(0); // important 27 | 28 | // Empezamos del reverso de las cadenas, es como una multiplicación normal 29 | for(let i = m - 1; i >= 0; i--) { 30 | for(let j = n - 1; j >= 0; j--) { 31 | let multiply = (parseInt(num1[i]) * parseInt(num2[j])); 32 | let p1 = i + j; 33 | let p2 = i + j + 1; 34 | let sum = multiply + posNum[p2]; 35 | 36 | // Este es el elemento que se puede traslapar 37 | posNum[p1] += sum / 10 | 0; 38 | // Este es el elemento de más a la derecha, no se translapa 39 | posNum[p2] = (sum) % 10 | 0; 40 | } 41 | } 42 | 43 | let result = ''; 44 | for (let index in posNum){ 45 | if (!(result.length == 0 && posNum[index] == 0)) { 46 | result += posNum[index]; 47 | } 48 | } 49 | return result.length == 0 ? "0" : result.toString(); 50 | }; 51 | 52 | n1 = "123456789"; 53 | n2 = "987654321"; 54 | console.log(multiply(n1, n2)); -------------------------------------------------------------------------------- /Palindromic Substring.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Given a string, your task is to count how many palindromic substrings in this string. 4 | 5 | The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters. 6 | 7 | Example 1: 8 | 9 | Input: "abc" 10 | Output: 3 11 | Explanation: Three palindromic strings: "a", "b", "c". 12 | 13 | 14 | Example 2: 15 | 16 | Input: "aaa" 17 | Output: 6 18 | Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa". 19 | 20 | https://leetcode.com/problems/palindromic-substrings/ 21 | 22 | NoteL 23 | Checar el problema de longest common substring y longest common subsequence 24 | */ 25 | 26 | // Idea is start from each index and try to extend palindrome for both odd and even length 27 | var countSubstrings = function(s) { 28 | let count = 0; 29 | 30 | for(let i = 0; i < s.length; i++) { 31 | // Odd length (Longitud par) 32 | let left = i; 33 | let right = i; 34 | while(left >= 0 && right < s.length && s[left] == s[right]) { 35 | left--; 36 | right++; 37 | count++; 38 | } 39 | 40 | // Even length (Longitud impar) 41 | left = i; 42 | right = i + 1; 43 | while(left >= 0 && right < s.length && s[left] == s[right]) { 44 | left--; 45 | right++; 46 | count++; 47 | } 48 | } 49 | return count; 50 | }; 51 | 52 | str = "abc"; 53 | console.log(countSubstrings(str)); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Facebook-Interview-Coding -------------------------------------------------------------------------------- /Random Pick up Index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array. 3 | 4 | Note: 5 | The array size can be very large. Solution that uses too much extra space will not pass the judge. 6 | 7 | Example: 8 | 9 | int[] nums = new int[] {1,2,3,3,3}; 10 | Solution solution = new Solution(nums); 11 | 12 | // pick(3) should return either index 2, 3, or 4 randomly. Each index should have equal probability of returning. 13 | solution.pick(3); 14 | 15 | // pick(1) should return 0. Since in the array only nums[0] is equal to 1. 16 | solution.pick(1); 17 | 18 | https://leetcode.com/problems/random-pick-index/ 19 | */ 20 | 21 | // O(N) Time complexity 22 | // O(1) Space complexity 23 | var Solution = function(nums) { 24 | this.nums = nums; 25 | }; 26 | 27 | /** 28 | * @param {number} target 29 | * @return {number} 30 | */ 31 | Solution.prototype.pick = function(target) { 32 | 33 | let countOcurrences = 0; 34 | let result = -1; 35 | 36 | // Count the number of ocurrences 37 | for(let i = 0; i < this.nums.length; i++) { 38 | if(this.nums[i] === target) { 39 | countOcurrences++; 40 | } 41 | } 42 | 43 | // Random element ocurrence, from 0 to N where N is the number of ocurrences 44 | let random = Math.floor(Math.random() * countOcurrences); 45 | for(let i = 0; i < this.nums.length; i++) { 46 | if(this.nums[i] === target) { 47 | random--; 48 | if(random === -1) { 49 | result = i; 50 | break; 51 | } 52 | } 53 | } 54 | 55 | return result; 56 | }; 57 | 58 | 59 | // O(N) Time complexity 60 | // O(N) Space complexity 61 | var Solution = function(nums) { 62 | this.hash = {}; 63 | 64 | // Fill hash 65 | let num; 66 | for(let i = 0; i < nums.length; i++) { 67 | num = nums[i]; 68 | if(nums[i] in this.hash) { 69 | this.hash[num].push(i); 70 | } else { 71 | this.hash[num] = [i]; 72 | } 73 | } 74 | }; 75 | 76 | /** 77 | * @param {number} target 78 | * @return {number} 79 | */ 80 | Solution.prototype.pick = function(target) { 81 | if(!(target in this.hash)) return -1; 82 | 83 | let options = this.hash[target]; 84 | let index = Math.floor(Math.random() * options.length); 85 | return options[index]; 86 | }; -------------------------------------------------------------------------------- /StackImplementationLinkedList.js: -------------------------------------------------------------------------------- 1 | /* Implement a stack using Linked List */ 2 | 3 | /*Implement stack*/ 4 | 5 | var Node = function(data) { 6 | this.data = data; 7 | this.next = null; 8 | } 9 | 10 | function Stack(){ 11 | this.top = null; 12 | } 13 | 14 | Stack.prototype.pop = function() { 15 | // If stack is not empty 16 | if(this.top) { 17 | // Get the top of the stack 18 | let item = this.top.data; 19 | // Update our top with the next of our stack 20 | this.top = this.top.next; 21 | return item; 22 | } 23 | return null; 24 | } 25 | 26 | Stack.prototype.push = function(data) { 27 | // Create new top of stack 28 | let node = new Node(data); 29 | // Link our new node with the rest of the stack 30 | node.next = this.top; 31 | // Update our stack with the new node 32 | this.top = node; 33 | } 34 | 35 | Stack.prototype.peek = function() { 36 | if(!this.top) { 37 | return -1; 38 | } 39 | return this.top.data; 40 | } 41 | 42 | let stack = new Stack(); 43 | stack.push(1); 44 | stack.push(2); 45 | stack.push(3); 46 | stack.push(4); 47 | stack.push(5); 48 | console.log(stack); 49 | stack.pop(); 50 | console.log(stack); 51 | console.log(stack.peek()); 52 | console.log(stack); -------------------------------------------------------------------------------- /Sub Array Sum.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. 3 | 4 | Example 1: 5 | Input:nums = [1,1,1], k = 2 6 | Output: 2 7 | 8 | https://leetcode.com/problems/subarray-sum-equals-k/ 9 | */ 10 | 11 | // Acumulative sum 12 | // Time complexity: O(N^2) 13 | // Space complexity: O(1) 14 | var subarraySum = function(nums, k) { 15 | let result = 0; 16 | for(let i = 0; i < nums.length; i++) { 17 | let sum = 0; 18 | for(let j = i; j < nums.length; j++) { 19 | sum += nums[j]; 20 | if(sum === k) { 21 | result++; 22 | } 23 | } 24 | } 25 | return result; 26 | }; 27 | 28 | // Time complexity: O(N) 29 | // Space complexity: O(N) 30 | var subarraySum = function(nums, k) { 31 | let result = 0; 32 | let sum = 0; 33 | let hash = {}; 34 | // In case we found the exact match 35 | // 0 with 1 seen 36 | hash[0] = 1; 37 | for(let i = 0; i < nums.length; i++) { 38 | sum += nums[i]; 39 | if(sum - k in hash) { 40 | result += hash[sum-k]; 41 | } 42 | // Si existe, incrementamos el número de veces 43 | // que hemos encontrado la suma, de lo contrario 44 | // ponemos un 1 45 | hash[sum] = hash[sum] ? hash[sum] + 1 : 1; 46 | } 47 | return result; 48 | }; 49 | 50 | array = [1,1,1]; 51 | k = 2; 52 | console.log(subarraySum(array, k)); -------------------------------------------------------------------------------- /Target Sum.js: -------------------------------------------------------------------------------- 1 | /* 2 | You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symbols + and -. 3 | For each integer, you should choose one from + and - as its new symbol. 4 | 5 | Find out how many ways to assign symbols to make sum of integers equal to target S. 6 | 7 | Example 1: 8 | Input: nums is [1, 1, 1, 1, 1], S is 3. 9 | Output: 5 10 | Explanation: 11 | 12 | -1+1+1+1+1 = 3 13 | +1-1+1+1+1 = 3 14 | +1+1-1+1+1 = 3 15 | +1+1+1-1+1 = 3 16 | +1+1+1+1-1 = 3 17 | 18 | There are 5 ways to assign symbols to make the sum of nums be target 3. 19 | Note: 20 | The length of the given array is positive and will not exceed 20. 21 | The sum of elements in the given array will not exceed 1000. 22 | Your output answer is guaranteed to be fitted in a 32-bit integer. 23 | 24 | https://leetcode.com/problems/target-sum/ 25 | 26 | Check https://github.com/wey068/Facebook-Interview-Coding/blob/master/494.%20TargetSum.java 27 | */ 28 | 29 | // DFS + Memoization 30 | var findTargetSumWays = function(nums, S) { 31 | // Index 32 | let i = 0; 33 | let memo = {}; 34 | return dfs(nums, S, i, memo); 35 | }; 36 | 37 | function dfs(nums, sum, i, memo) { 38 | // Generate the key 39 | let key = i + ":" + sum; 40 | if(key in memo) { 41 | return memo[key]; 42 | } 43 | 44 | // Count the number of ways if the sum is equal to 0, we should use the number of element in our input array 45 | if(i === nums.length) { 46 | return sum === 0 ? 1 : 0; 47 | } 48 | 49 | // Invert the signs here to reach the 0 depending if we need to add or substract 50 | let add = dfs(nums, sum - nums[i], i + 1, memo); 51 | let minus = dfs(nums, sum + nums[i], i + 1, memo); 52 | 53 | // Save our partial response 54 | memo[key] = add + minus; 55 | return add + minus; 56 | } 57 | 58 | nums = [1, 1, 1, 1, 1]; 59 | S = 3; 60 | console.log(findTargetSumWays(nums, S)); -------------------------------------------------------------------------------- /Two Sum.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers, return indices of the two numbers such that they add up to a specific target. 3 | 4 | You may assume that each input would have exactly one solution, and you may not use the same element twice. 5 | 6 | Example: 7 | Given nums = [2, 7, 11, 15], target = 9, 8 | 9 | Because nums[0] + nums[1] = 2 + 7 = 9, 10 | return [0, 1]. 11 | 12 | Complex O(n) 13 | */ 14 | 15 | /** 16 | * @param {number[]} nums 17 | * @param {number} target 18 | * @return {number[]} 19 | */ 20 | var twoSum = function(nums, target) { 21 | var hash = {}; 22 | var complement = 0; 23 | var element = 0; 24 | 25 | for(var i = 0; i < nums.length; i++){ 26 | //Store the element in the array for quick access 27 | element = nums[i]; 28 | //We need to check the complement for the target 29 | complement = target - element; 30 | //If we saw the complement, we have found the indexs 31 | if(complement in hash){ 32 | return [hash[complement], i]; 33 | }else{ //We store the element with the index it has 34 | hash[element] = i; 35 | } 36 | } 37 | }; 38 | 39 | nums = [2, 7, 11, 15]; 40 | target = 9; 41 | console.log(twoSum(nums,target)); 42 | 43 | var twoSumWithDuplicates = function(array, target) { 44 | let map = {}; 45 | // Result has the indexes of the elements 46 | let result = []; 47 | 48 | for(let i = 0; i < array.length; i++) { 49 | if(!(array[i] in map)) { 50 | // Puede ser también un set 51 | // map[array[i]] = new Set(); 52 | map[array[i]] = []; 53 | } 54 | map[array[i]].push(i); 55 | 56 | if(target - array[i] in map) { 57 | let set = map[target - array[i]]; 58 | set.forEach((item) => { 59 | // Does not allow duplicates numbers, the same index can not be used 60 | if(item !== i) { 61 | result.push([i, item]); 62 | } 63 | }); 64 | } 65 | } 66 | return result; 67 | } 68 | 69 | array = [2, 4, 3, 4, 4, 6]; 70 | target = 8; 71 | console.log(twoSumWithDuplicates(array, target)); -------------------------------------------------------------------------------- /addBinary.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Given two binary strings, return their sum (also a binary string). 4 | 5 | For example, 6 | a = "11" 7 | b = "1" 8 | Return "100". 9 | 10 | https://leetcode.com/problems/add-binary/description/ 11 | */ 12 | 13 | var addBinary = function(a, b) { 14 | let i = a.length - 1; 15 | let j = b.length - 1; 16 | let result = ''; 17 | let carry = 0; 18 | 19 | while(i >= 0 || j >= 0) { 20 | let sum = carry; 21 | 22 | // Convert into digit a string, check outbounds 23 | if(i >= 0) { 24 | sum += a[i--] * 1; // Implicit conversion 25 | } 26 | 27 | if(j >= 0) { 28 | sum += b[j--] * 1; // Implicit conversion 29 | } 30 | 31 | // We can only have a sum of 0, 1 or 2, we can not sum a higher number with binary data 0,1 32 | result = (sum%2) + result; 33 | carry = sum / 2 | 0; 34 | } 35 | 36 | // The last two digits may have a carry, so let's check it out 37 | if(carry > 0) { 38 | result = carry + result; 39 | } 40 | 41 | return result; 42 | }; 43 | 44 | var addBinary = function(str, str2){ 45 | let result = ''; 46 | let i = str.length-1; 47 | let j = str2.length-1; 48 | let carry = false; 49 | let tmp; 50 | let n1,n2; 51 | while(i >= 0 || j >= 0 || carry){ 52 | n1 = str[i] || '0'; 53 | n2 = str2[j] || '0'; 54 | if((n1 === '1' && n2 === '0') || (n1 === '0' && n2 === '1')){ 55 | /*Si tenemos carry entonces sería el caso de (1+0) + 1 = 0 con carry 1 56 | o si no tenemos carry unicamente es 0 sin carry*/ 57 | tmp = carry ? '0' : '1'; 58 | 59 | }else if(n1 === '0' && n2 === '0'){ 60 | /*En este caso no tenemos carry de ninguna forma, sólo podemos 61 | obtener un uno o cero dependiendo si tenemos carry*/ 62 | tmp = carry ? '1' : '0'; 63 | carry = false; 64 | }else{ 65 | /*Al entrar a esta condicion es porque los dos números son 1 y 1 66 | en este caso siemre existirá un flag y sólo debemos verificar si 67 | ponemos 1 y 0 dependiendo de si tenemos un anterior carry*/ 68 | tmp = carry ? '1' : '0' 69 | carry = true; 70 | } 71 | result = tmp + result; 72 | i--; 73 | j--; 74 | } 75 | return result; 76 | } 77 | 78 | var addBinary = function(str, str2){ 79 | let result = []; 80 | let i = str.length-1; 81 | let j = str2.length-1; 82 | let carry = false; 83 | let n1,n2; 84 | while(i >= 0 || j >= 0 || carry){ 85 | n1 = str[i] ? str[i] : '0'; 86 | n2 = str2[j] ? str2[j] : '0'; 87 | if(n1 === '1' && n2 === '0' || n1 === '0' && n2 === '1'){ 88 | /*Si tenemos carry entonces sería el caso de (1+0) + 1 = 0 con carry 1 89 | o si no tenemos carry unicamente es 0 sin carry*/ 90 | result.unshift(carry ? '0' : '1'); 91 | }else if(n1 === '0' && n2 === '0'){ 92 | /*En este caso no tenemos carry de ninguna forma, sólo podemos 93 | obtener un uno o cero dependiendo si tenemos carry*/ 94 | result.unshift(carry ? '1' : '0'); 95 | carry = false; 96 | }else{ 97 | /*Al entrar a esta condicion es porque los dos números son 1 y 1 98 | en este caso siemre existirá un flag y sólo debemos verificar si 99 | ponemos 1 y 0 dependiendo de si tenemos un anterior carry*/ 100 | result.unshift(carry ? '1' : '0'); 101 | carry = true; 102 | } 103 | i--; 104 | j--; 105 | } 106 | return result.join(''); 107 | } 108 | 109 | a = "11"; 110 | b = "1"; 111 | console.log(addBinary(a,b)); 112 | -------------------------------------------------------------------------------- /addOperators.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string that contains only digits 0-9 and a target value, return all possibilities to add binary operators (not unary) +, -, or * 3 | between the digits so they evaluate to the target value. 4 | 5 | Example 1: 6 | 7 | Input: num = "123", target = 6 8 | Output: ["1+2+3", "1*2*3"] 9 | Example 2: 10 | 11 | Input: num = "232", target = 8 12 | Output: ["2*3+2", "2+3*2"] 13 | Example 3: 14 | 15 | Input: num = "105", target = 5 16 | Output: ["1*0+5","10-5"] 17 | Example 4: 18 | 19 | Input: num = "00", target = 0 20 | Output: ["0+0", "0-0", "0*0"] 21 | Example 5: 22 | 23 | Input: num = "3456237490", target = 9191 24 | Output: [] 25 | 26 | https://leetcode.com/problems/expression-add-operators/description/ 27 | */ 28 | 29 | var addOperators = function(num, target) { 30 | let result = []; 31 | let start = 0; 32 | let eval = 0; 33 | let mult = 0; 34 | let str = '' 35 | dfs(result, str, num, target, start, eval, mult); 36 | return result; 37 | }; 38 | 39 | // Mult it's important to carry it for using the multiply option 40 | function dfs(result, str, num, target, start, eval, mult) { 41 | // Base case 42 | if(start === num.length) { 43 | if(eval === target) { 44 | result.push(str); 45 | } 46 | return; 47 | } 48 | 49 | for(let i = start; i < num.length; i++) { 50 | if(num[start] === '0' && i !== start) break; // Can not be leading 0s, so let's break the recursion 51 | // 123 = 1, 12, 123, this is the value of current 52 | let current = parseInt(num.substring(start, i + 1)); 53 | // For the case we just need to add in the string the number 54 | if(start === 0) { 55 | dfs(result, str + current, num, target, i + 1, current, current); 56 | } else { 57 | // Get all combinations 58 | dfs(result, str + '+' + current, num, target, i + 1, eval + current, current); 59 | 60 | dfs(result, str + '-' + current, num, target, i + 1, eval - current, -current); 61 | 62 | dfs(result, str + '*' + current, num, target, i + 1, eval - mult + mult * current, mult * current); 63 | } 64 | } 65 | } 66 | 67 | num = "123"; 68 | target = 6; 69 | console.log(addOperators(num, target)); -------------------------------------------------------------------------------- /autocompleteDictionaryTrie.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a trie, return a list of words that matches with a given prefix 3 | */ 4 | 5 | let trie = {children: {}, count: 0, string: null}; 6 | const addWord = function(word) { 7 | let node = trie; 8 | for(let i = 0; i < word.length; i++) { 9 | //Asigna el nodo si lo encuentra o agrega un elemento para agregarlo al trie 10 | node.children[word[i]] = node.children[word[i]] || {children: {}, count: 0, isWord: null}; 11 | // Recorre el nodo 12 | node = node.children[word[i]]; 13 | // Cuenta las veces que se ha visto 14 | node.count++; 15 | } 16 | // Marca el end de la palabra 17 | node.isWord = word; 18 | } 19 | 20 | // Add words to the tree 21 | addWord('google'); 22 | addWord('good'); 23 | addWord('great'); 24 | // console.log(trie); 25 | 26 | let result = []; 27 | function findWords(prefix) { 28 | let node = trie; 29 | dfs(prefix, 0, node); 30 | return result; 31 | } 32 | 33 | function dfs(prefix, index, node) { 34 | if(index < prefix.length) { 35 | let letter = prefix[index]; 36 | if(node.children[letter]) { 37 | dfs(prefix, index + 1, node.children[letter]); 38 | } else { 39 | return; 40 | } 41 | } else { 42 | if(node.isWord) { 43 | result.push(node.isWord); 44 | } else { 45 | for(let op in node.children) { 46 | dfs(prefix, index, node.children[op]); 47 | } 48 | } 49 | } 50 | } 51 | 52 | let prefix = 'goo'; 53 | console.log(findWords(prefix)); -------------------------------------------------------------------------------- /badVersion.js: -------------------------------------------------------------------------------- 1 | /* 2 | so bad. 3 | 4 | Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad. 5 | 6 | You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API. 7 | 8 | Example: 9 | 10 | Given n = 5, and version = 4 is the first bad version. 11 | 12 | call isBadVersion(3) -> false 13 | call isBadVersion(5) -> true 14 | call isBadVersion(4) -> true 15 | 16 | Then 4 is the first bad version. 17 | 18 | https://leetcode.com/problems/first-bad-version/description/ 19 | 20 | /* 21 | 22 | /** 23 | * Definition for isBadVersion() 24 | * 25 | * @param {integer} version number 26 | * @return {boolean} whether the version is bad 27 | * isBadVersion = function(version) { 28 | * ... 29 | * }; 30 | */ 31 | 32 | /** 33 | * @param {function} isBadVersion() 34 | * @return {function} 35 | */ 36 | var solution = function(isBadVersion) { 37 | /** 38 | * @param {integer} n Total versions 39 | * @return {integer} The first bad version 40 | */ 41 | // Binary Search 42 | return function(n) { 43 | let left = 0; 44 | let right = n - 1; 45 | while(left <= right) { 46 | let middle = Math.floor((left + right)/2); 47 | if(isBadVersion(middle)) { 48 | right = middle - 1; 49 | } else { 50 | left = middle + 1; 51 | } 52 | } 53 | 54 | return left; 55 | }; 56 | }; -------------------------------------------------------------------------------- /bestTimeToSellStock.js: -------------------------------------------------------------------------------- 1 | /* 2 | Say you have an array for which the ith element is the price of a given stock on day i. 3 | 4 | If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), 5 | design an algorithm to find the maximum profit. 6 | 7 | Note that you cannot sell a stock before you buy one. 8 | 9 | Example 1: 10 | 11 | Input: [7,1,5,3,6,4] 12 | Output: 5 13 | Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. 14 | Not 7-1 = 6, as selling price needs to be larger than buying price. 15 | Example 2: 16 | 17 | Input: [7,6,4,3,1] 18 | Output: 0 19 | Explanation: In this case, no transaction is done, i.e. max profit = 0. 20 | 21 | https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ 22 | */ 23 | 24 | /** 25 | * @param {number[]} prices 26 | * @return {number} 27 | */ 28 | var maxProfit = function(prices) { 29 | 30 | if(!prices.length) return 0; 31 | 32 | let min = prices[0]; 33 | let result = 0; 34 | 35 | for(let i = 1; i < prices.length; i++) { 36 | if(prices[i] < min) min = prices[i] 37 | else result = Math.max(result, prices[i] - min) 38 | } 39 | return result; 40 | }; 41 | 42 | 43 | /** 44 | * @param {number[]} prices 45 | * @return {number} 46 | */ 47 | var maxProfit = function(prices) { 48 | // Kadane's Algorithm 49 | /* 50 | All the straight forward solution should work, but if the interviewer twists the question slightly by giving the 51 | difference array of prices, Ex: for {1, 7, 4, 11}, if he gives {0, 6, -3, 7}, you might end up being confused. 52 | Here, the logic is to calculate the difference (maxCur += prices[i] - prices[i-1]) of the original array, and find 53 | a contiguous subarray giving maximum profit. If the difference falls below 0, reset it to zero. 54 | 55 | I spent some time convincing myself about why we need to reset to zero. By reseting maxCur to 0, essentially it 56 | means that we have found a point i where the price[i] is lower than the time we bought, and that we should then try 57 | to buy at point i to see if we can achieve a bigger gain. Because maxCur is recording the difference, the 58 | difference between price[i] and itself should be 0 59 | */ 60 | let currentMax = 0; 61 | let maxSoFar = 0; 62 | for(let i = 1; i < prices.length; i++) { 63 | currentMax += prices[i] - prices[i-1]; 64 | currentMax = Math.max(0, currentMax); 65 | maxSoFar = Math.max(maxSoFar, currentMax); 66 | } 67 | return maxSoFar; 68 | }; 69 | 70 | /* 71 | Say you have an array for which the ith element is the price of a given stock on day i. 72 | 73 | Design an algorithm to find the maximum profit. You may complete as many transactions as you 74 | like (i.e., buy one and sell one share of the stock multiple times). 75 | 76 | Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again). 77 | 78 | Example 1: 79 | 80 | Input: [7,1,5,3,6,4] 81 | Output: 7 82 | Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. 83 | Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. 84 | 85 | https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/ 86 | 87 | */ 88 | 89 | var maxProfit = function(prices) { 90 | let result = 0; 91 | for(let i = 1; i < prices.length; i++) { 92 | // Math with 0 to reset in case it's a negative number 93 | result += Math.max(0, prices[i] - prices[i-1]); 94 | } 95 | return result; 96 | }; -------------------------------------------------------------------------------- /binaryTreePaths.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Given a binary tree, return all root-to-leaf paths. 4 | 5 | Note: A leaf is a node with no children. 6 | 7 | Example: 8 | 9 | Input: 10 | 11 | 1 12 | / \ 13 | 2 3 14 | \ 15 | 5 16 | 17 | Output: ["1->2->5", "1->3"] 18 | 19 | Explanation: All root-to-leaf paths are: 1->2->5, 1->3 20 | 21 | https://leetcode.com/problems/binary-tree-paths/description/ 22 | 23 | */ 24 | 25 | var binaryTreePaths = function(root) { 26 | let result = []; 27 | dfs(root, '', result); 28 | return result; 29 | }; 30 | 31 | // Walk preorder 32 | function dfs(node, tmp, result){ 33 | // Base case 34 | if(!node) return; 35 | 36 | // Preorder action 37 | tmp = tmp ? tmp + '->' + node.val : node.val; 38 | if(!node.left && !node.right){ 39 | // No es necesario limpiar porque a la vuelta rompera con el base case 40 | result.push(tmp); 41 | } 42 | dfs(node.left, tmp, result); 43 | dfs(node.right, tmp, result); 44 | } 45 | 46 | // Iterative preorder traversal 47 | // Time complexity O(N) -- We touch every single node 48 | // Space complexity O(N) -- Worst case we can have all nodes in the stack 49 | function binaryTreePaths(root) { 50 | 51 | if(!root) { 52 | return []; 53 | } 54 | 55 | let node = root; 56 | // Stack to traverse preorder 57 | let stack = []; 58 | // Result to push the strings 59 | let result = []; 60 | // Stack of strings 61 | let paths = []; 62 | 63 | stack.push(node); 64 | paths.push(node.val + ''); 65 | 66 | while(stack.length) { 67 | let current = stack.pop(); 68 | // Path is the concatenation in preorder traversal 69 | let path = paths.pop(); 70 | 71 | // Check if is leaf node (Action) 72 | if(!current.left && !current.right) { 73 | result.push(path.toString()); 74 | } 75 | 76 | if(current.right) { 77 | stack.push(current.right); 78 | paths.push(path + '->' + current.right.val); 79 | } 80 | if(current.left) { 81 | stack.push(current.left); 82 | paths.push(path + '->' + current.left.val); 83 | } 84 | } 85 | 86 | return result; 87 | } 88 | 89 | // BFS 90 | var binaryTreePaths = function(root) { 91 | if(!root) { 92 | return []; 93 | } 94 | 95 | let map = {} // (node, parent node); 96 | let queue = []; 97 | let queueStr = []; 98 | queue.push(root); 99 | queueStr.push(""); 100 | map[root] = null; 101 | result = []; 102 | 103 | while(queue.length) { 104 | let node = queue.shift(); 105 | let currStr = queueStr.shift(); 106 | 107 | // Action 108 | console.log(node.val); 109 | // It´s a leaf node 110 | if(!node.left && !node.right) { 111 | //let str = getPaths(map, node); 112 | result.push(currStr + node.val); 113 | } 114 | 115 | 116 | if(node.left) { 117 | queue.push(node.left); 118 | queueStr.push(currStr + node.val + '->'); 119 | map[node.left] = node; 120 | } 121 | if(node.right) { 122 | queue.push(node.right); 123 | queueStr.push(currStr + node.val + '->'); 124 | map[node.right] = node; 125 | } 126 | } 127 | 128 | return result; 129 | }; 130 | 131 | // Opción 1 132 | function Node(val, left, right){ 133 | this.val = val; 134 | this.left = left || null; 135 | this.right = right || null; 136 | } 137 | 138 | 139 | var binaryTreePaths = function(root) { 140 | let result = []; 141 | let tmp = []; 142 | dfs(root, tmp, result); 143 | return result; 144 | }; 145 | 146 | // Walk preorder 147 | function dfs(node, tmp, result){ 148 | // Or (!node) return 149 | if(node) { 150 | tmp.push(node.val); 151 | if(!node.left && !node.right){ 152 | result.push(tmp.join('->')); 153 | } 154 | dfs(node.left, tmp.concat(), result); 155 | dfs(node.right, tmp.concat(), result); 156 | } 157 | } 158 | 159 | // Opción 2 160 | function Node(val, left, right){ 161 | this.val = val; 162 | this.left = left || null; 163 | this.right = right || null; 164 | } 165 | 166 | 167 | var binaryTreePaths = function(root) { 168 | let result = []; 169 | let tmp = []; 170 | dfs(root, tmp, result); 171 | return result; 172 | }; 173 | 174 | function dfs(node, helper, result){ 175 | if(node) { 176 | helper.push(node.val); 177 | if(!node.left && !node.right){ 178 | result.push(helper.join('->')); 179 | } 180 | dfs(node.left, [...helper], result); 181 | dfs(node.right,[...helper], result); 182 | } 183 | } 184 | 185 | tree = new Node(1, new Node(2, null, new Node(5)), new Node(3)); 186 | console.log(binaryTreePaths(tree)); 187 | 188 | // Opción 3 189 | 190 | /* 191 | 1 192 | 2 3 193 | 4 5 6 7 194 | 195 | Result = [1,2,3] [1,2,5] [1,3,6] [1,3,7] 196 | */ 197 | 198 | function Node(val, left=null, right=null) { 199 | this.val = val; 200 | this.left = left; 201 | this.right = right; 202 | } 203 | 204 | var getTreePaths = (node, array) => { 205 | if(!node) { 206 | console.log(' '); 207 | return; 208 | } 209 | array.push(node.val); 210 | if(node.left || node.right) { 211 | if(node.left) { 212 | getTreePaths(node.left, array); 213 | } 214 | if(node.right) { 215 | getTreePaths(node.right, array) 216 | } 217 | } else { 218 | console.log(array.join('->')); 219 | } 220 | array.pop(); 221 | } 222 | 223 | tree = new Node(1, new Node(2, new Node(4), new Node(5)), new Node(3, new Node(6), new Node(7))); 224 | console.log(getTreePaths(tree, [])); 225 | -------------------------------------------------------------------------------- /cloneGraph.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Given the head of a graph, return a deep copy (clone) of the graph. Each node in the graph contains a label (int) and a list (List[UndirectedGraphNode]) of its neighbors. There is an edge between the given node and each of the nodes in its neighbors. 4 | 5 | 6 | OJ's undirected graph serialization (so you can understand error output): 7 | Nodes are labeled uniquely. 8 | 9 | We use # as a separator for each node, and , as a separator for node label and each neighbor of the node. 10 | 11 | 12 | As an example, consider the serialized graph {0,1,2#1,2#2,2}. 13 | 14 | The graph has a total of three nodes, and therefore contains three parts as separated by #. 15 | 16 | First node is labeled as 0. Connect node 0 to both nodes 1 and 2. 17 | Second node is labeled as 1. Connect node 1 to node 2. 18 | Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle. 19 | 20 | 21 | Visually, the graph looks like the following: 22 | 23 | 1 24 | / \ 25 | / \ 26 | 0 --- 2 27 | / \ 28 | \_/ 29 | Note: The information about the tree serialization is only meant so that you can understand error output if you get a wrong answer. You don't need to understand the serialization to solve the problem. 30 | 31 | 32 | https://leetcode.com/problems/clone-graph/ 33 | 34 | */ 35 | 36 | 37 | /** 38 | * Definition for undirected graph. 39 | * class UndirectedGraphNode { 40 | * int label; 41 | * List neighbors; 42 | * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } 43 | * }; 44 | */ 45 | public class Solution { 46 | public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 47 | Map map = new HashMap<>(); 48 | return dfsClone(node, map); 49 | } 50 | 51 | public UndirectedGraphNode dfsClone(UndirectedGraphNode node, Map map) { 52 | if (node == null) return null; 53 | if (map.containsKey(node.label)) return map.get(node.label); 54 | UndirectedGraphNode cloneNode = new UndirectedGraphNode(node.label); 55 | map.put(cloneNode.label, cloneNode); 56 | for (UndirectedGraphNode n : node.neighbors) 57 | cloneNode.neighbors.add(dfsClone(n, map)); 58 | return cloneNode; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /combinationSum4.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer array with all positive numbers and no duplicates, find the number of possible combinations 3 | that add up to a positive integer target. 4 | 5 | Example: 6 | 7 | nums = [1, 2, 3] 8 | target = 4 9 | 10 | The possible combination ways are: 11 | (1, 1, 1, 1) 12 | (1, 1, 2) 13 | (1, 2, 1) 14 | (1, 3) 15 | (2, 1, 1) 16 | (2, 2) 17 | (3, 1) 18 | 19 | Note that different sequences are counted as different combinations. 20 | 21 | Therefore the output is 7. 22 | Follow up: 23 | What if negative numbers are allowed in the given array? 24 | How does it change the problem? 25 | What limitation we need to add to the question to allow negative numbers? 26 | 27 | https://leetcode.com/problems/combination-sum-iv/ 28 | https://www.programcreek.com/2014/07/leetcode-combination-sum-iv-java/ 29 | http://www.cnblogs.com/grandyang/p/5705750.html 30 | http://anothercasualcoder.blogspot.com/2016/12/leetcode-combination-sum-iv.html 31 | 32 | Coin change 33 | https://www.programcreek.com/2015/04/leetcode-coin-change-java/ 34 | 35 | Time complexity: O(nlogn + target*n) 36 | */ 37 | 38 | /* 39 | Run: 40 | [1,2,3] target = 4 41 | dp[0] = 1, 42 | dp[1] = 1, 43 | dp[2] = 1 + 1 = 2, 44 | dp[3] = 1 + 1 + 2 = 4, 45 | dp[4] = 1 + 2 + 4 = 7 (we have no 4 in nums, so dp[4] = 1 + 2 + 4 = 7, not 1 + 1 + 2 + 4 = 8) 46 | */ 47 | 48 | // we know that target is the sum of numbers in the array. Imagine we only need one more number to reach target, 49 | // this number can be any one in the array, right? So the # of combinations of target, comb[target] = sum(comb[target - nums[i]]), 50 | // where 0 <= i < nums.length, and target >= nums[i]. 51 | // In the example given, we can actually find the # of combinations of 4 with the # of combinations of 3(4 - 1), 2(4- 2) and 1(4 - 3). 52 | // As a result, comb[4] = comb[4-1] + comb[4-2] + comb[4-3] = comb[3] + comb[2] + comb[1]. 53 | 54 | /* 55 | *****Follow Up***** 56 | 57 | What if negative numbers are allowed in the given array? 58 | Then adding a num to the combination is not guaranteed to be increasing, which means I can add a huge bounch of negative nums 59 | and add a huge bounch of positive nums to achieve a target sum. 60 | eg.target=0:[-1,1],[-1,-1,1,1],[-1,-1,-1,1,1,1]... 61 | 62 | How does it change the problem? 63 | We will have lots of lots of possible combinations, even infinity. 64 | 65 | What limitation we need to add to the question to allow negative numbers? 66 | For example, each negative num can only be used once, etc. 67 | */ 68 | var combinationSum4 = function(nums, target) { 69 | if(!nums.length) return 0; 70 | let dp = new Array(target + 1).fill(0); 71 | 72 | dp[0] = 1; 73 | nums.sort((a,b) => a - b); 74 | 75 | // if target is much larger than num of nums, we can sort nums and break the inner for loop if j > i 76 | for(let i = 0; i <= target; i++) { 77 | for(let j = 0; j < nums.length && nums[j] <= i; j++) { 78 | dp[i] = dp[i] + dp[i - nums[j]]; 79 | } 80 | } 81 | 82 | return dp[target]; 83 | }; 84 | 85 | nums = [1, 2, 3]; 86 | target = 4; 87 | console.log(combinationSum4(nums, target)); -------------------------------------------------------------------------------- /convertBSTToDoubleList.js: -------------------------------------------------------------------------------- 1 | /* 2 | // http://articles.leetcode.com/convert-binary-search-tree-bst-to/ 3 | 4 | When I first see this problem, my first thought was in-order traversal. Couldn’t we modify the nodes’ left and right pointers as we 5 | do an in-order traversal of the tree? However, we have to beware not to modify the pointers and accessing it at a later time. 6 | 7 | As we traverse the tree in-order, we could safely modify a node’s left pointer to point to the previously traversed node as we 8 | never use it once we reach a node. We would also need to modify the previously traversed node’s right pointer to point to the current 9 | node. Note: The previously traversed node meant here is not its parent node. It is the node’s previous smaller element. 10 | 11 | Easy approach, right? But wait, we are still missing two more steps. First, we did not assign the list’s head pointer. Second, the last 12 | element’s right pointer does not point to the first element (similar to the first element’s left pointer). 13 | 14 | How do we solve this? My approach is pretty easy: Just update the current node’s right pointer to point back to the head and the head’s 15 | left pointer to point to current node in each recursive call. As the recursion ends, the list’s head and tail would be automagically 16 | updated with the correct pointers. Don’t forget to check for this special case: A list with only one element should have its left and 17 | right pointers both pointing back to itself. 18 | 19 | 20 | A double-linked list with a length of one. 21 | Do you think this approach works? I bet it did! The run time complexity for this solution is O(N) since we are essentially 22 | doing a modified in-order traversal. It does have some extra assignments in each recursive call though. But overall I am quite 23 | satisfied with this approach because it is intuitive and easy to follow. Besides, we are adapting an existing 24 | algorithm (in-order traversal) to solve this problem, isn’t this just neat? 25 | */ 26 | 27 | function TreeNode(val, left, right) { 28 | this.val = val; 29 | this.left = left || null; 30 | this.right = right || null; 31 | } 32 | 33 | // O(n) time, O(h) space 34 | let prev = null; 35 | let head = null; 36 | function convertBSTtoCircularDL(tree) { 37 | inorder(tree); 38 | return head; 39 | } 40 | 41 | function inorder(node) { 42 | if(!node) return; 43 | 44 | inorder(node.left); 45 | 46 | node.left = prev; 47 | if(prev) { 48 | prev.right = node; // previous node's right points to current node 49 | } else { 50 | head = node; 51 | } 52 | 53 | // current node (smallest element) is head of 54 | // the list if previous node is not available 55 | // as soon as the recursion ends, the head's left pointer 56 | // points to the last node, and the last node's right pointer 57 | // points to the head pointer. 58 | 59 | let right = node.right; 60 | 61 | // This is to point the last element and the heas od the list 62 | // In each recursion we update the values 63 | head.left = node; 64 | node.right = head; 65 | 66 | // Update previous node 67 | prev = node; 68 | 69 | inorder(right); 70 | } 71 | 72 | tree = new TreeNode(4, new TreeNode(2, new TreeNode(1), new TreeNode(3)), new TreeNode(5)); 73 | console.log(convertBSTtoCircularDL(tree)); -------------------------------------------------------------------------------- /convertPreorderToBST.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversa/ 3 | */ 4 | 5 | function TreeNode(val, left, right) { 6 | this.val = val; 7 | this.left = left || null; 8 | this.right = right || null; 9 | } 10 | 11 | function constructBSTFromPreorder(array) { 12 | let index = {prev: 0}; 13 | return constructTreeUtil(array, 0, array.length - 1, index); 14 | } 15 | 16 | // O(n^2) 17 | function constructTreeUtil(array, low, high, index) { 18 | // Base case 19 | if(index.prev >= array.length || low > high) { 20 | return; 21 | } 22 | 23 | // The first element in the preorder traversal is the node 24 | // So take tha node of preindex and make it root 25 | let root = new TreeNode(array[index.prev]); 26 | index.prev++; 27 | 28 | // If we have only one element, return 29 | if(low === high) { 30 | return root; 31 | } 32 | 33 | // Search for the first element greater than root, this is the right subtree 34 | // Find the first element that satisfies the condition 35 | let i = low; 36 | for(; i < array.length; i++) { 37 | if(array[i] > root.val) { 38 | break; 39 | } 40 | } 41 | 42 | root.left = constructTreeUtil(array, index.prev, i - 1, index); 43 | root.right = constructTreeUtil(array, i, high, index); 44 | 45 | return root; 46 | } 47 | 48 | // O(N) 49 | let index = 0; 50 | function constructBSTFromPreorder(array) { 51 | return constructTreeUtil(array, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); 52 | } 53 | 54 | function constructTreeUtil(array, min, max) { 55 | // Base Case 56 | if(index >= array.length) { 57 | return; 58 | } 59 | 60 | if(array[index] <= min || array[index] >= max) { 61 | return; 62 | } 63 | 64 | let root = new TreeNode(array[index++]); 65 | root.left = constructTreeUtil(array, min, root.val); 66 | root.right = constructTreeUtil(array, root.val, max); 67 | 68 | return root; 69 | } 70 | 71 | // O(N) 72 | function constructBSTFromPreorder(array) { 73 | let index = {prev: 0}; 74 | return constructTreeUtil(array, array[0], Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, index); 75 | } 76 | 77 | function constructTreeUtil(array, value, min, max, index) { 78 | // Base Case 79 | if(index.prev > array.length) { 80 | return; 81 | } 82 | 83 | if(value > min && value < max) { 84 | let root = new TreeNode(value); 85 | index.prev++; 86 | 87 | if(index.prev < array.length) { 88 | 89 | root.left = constructTreeUtil(array, array[index.prev], min, value, index); 90 | 91 | root.right = constructTreeUtil(array, array[index.prev], value, max, index); 92 | } 93 | 94 | return root; 95 | } 96 | } 97 | 98 | 99 | /* 100 | 10 101 | 5 40 102 | 1 7 50 103 | */ 104 | 105 | /* 106 | 10 107 | / \ 108 | / \ 109 | {5, 1, 7} {40, 50} 110 | */ 111 | 112 | // Preorder array 113 | array = [10, 5, 1, 7, 40, 50] ; 114 | console.log(constructBSTFromPreorder(array)); -------------------------------------------------------------------------------- /countAndSay.js: -------------------------------------------------------------------------------- 1 | /* 2 | The count-and-say sequence is the sequence of integers with the first five terms as following: 3 | 4 | 1. 1 5 | 2. 11 6 | 3. 21 7 | 4. 1211 8 | 5. 111221 9 | 1 is read off as "one 1" or 11. 10 | 11 is read off as "two 1s" or 21. 11 | 21 is read off as "one 2, then one 1" or 1211. 12 | Given an integer n, generate the nth term of the count-and-say sequence. 13 | 14 | Note: Each term of the sequence of integers will be represented as a string. 15 | 16 | Example 1: 17 | 18 | Input: 1 19 | Output: "1" 20 | Example 2: 21 | 22 | Input: 4 23 | Output: "1211" 24 | https://leetcode.com/problems/count-and-say/description/ 25 | 26 | */ 27 | 28 | var countAndSay = function(n){ 29 | if(n === 1) return "1"; 30 | if(n === 2) return "11"; 31 | 32 | var str = "11"; 33 | var currentStr = null; 34 | for(let i = 3; i <= n; i++){ 35 | str = formStr(str); 36 | } 37 | return str; 38 | }; 39 | 40 | //String compression 41 | function formStr(str){ 42 | var count = 1; 43 | var tmp = ''; 44 | for(var i = 0; i < str.length; i++){ 45 | if(str[i] === str[i+1]){ 46 | count++; 47 | }else{ 48 | tmp += count + str[i]; 49 | count = 1; 50 | } 51 | } 52 | return tmp; 53 | }; 54 | 55 | n = 6; 56 | console.log(countAndSay(n)); 57 | -------------------------------------------------------------------------------- /decodeString.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an encoded string, return it's decoded string. 3 | 4 | The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being 5 | repeated exactly k times. Note that k is guaranteed to be a positive integer. 6 | 7 | You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc. 8 | 9 | Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 2[4]. 10 | 11 | Examples: 12 | 13 | s = "3[a]2[bc]", return "aaabcbc". 14 | s = "3[a2[c]]", return "accaccacc". 15 | s = "2[abc]3[cd]ef", return "abcabccdcdcdef". 16 | 17 | https://leetcode.com/problems/decode-string/description/ 18 | */ 19 | 20 | // Using stacks 21 | 22 | var decodeString = function(s) { 23 | let regex = /\d/; 24 | let stackStr = []; 25 | let stackNumber = []; 26 | let num = ''; 27 | let char; 28 | let currentStr = ''; 29 | for(let i = 0; i < s.length; i++) { 30 | char = s[i]; 31 | // If we have a digit, keep looking for the number 32 | if(regex.test(char)) { 33 | num += char; 34 | } else if (char === '[') { 35 | // This condition because we can have nested values with [] 36 | stackNumber.push(parseInt(num)) 37 | stackStr.push(currentStr); 38 | num = ''; 39 | currentStr = ''; 40 | } else if (char === ']') { 41 | prevStr = stackStr.pop(); 42 | times = stackNumber.pop() 43 | currentStr = prevStr + currentStr.repeat(times); 44 | } else { 45 | // Keep getting elements 46 | currentStr += char; 47 | } 48 | } 49 | return currentStr; 50 | }; 51 | 52 | s = "3[a]2[bc]"; // return "aaabcbc". 53 | // s = "3[a2[c]]" // "accaccacc" 54 | console.log(decodeString(s)); 55 | -------------------------------------------------------------------------------- /decodeWays.js: -------------------------------------------------------------------------------- 1 | /* 2 | A message containing letters from A-Z is being encoded to numbers using the following mapping: 3 | 4 | 'A' -> 1 5 | 'B' -> 2 6 | ... 7 | 'Z' -> 26 8 | Given a non-empty string containing only digits, determine the total number of ways to decode it. 9 | 10 | Example 1: 11 | 12 | Input: "12" 13 | Output: 2 14 | Explanation: It could be decoded as "AB" (1 2) or "L" (12). 15 | Example 2: 16 | 17 | Input: "226" 18 | Output: 3 19 | Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). 20 | 21 | https://youtu.be/qli-JCrSwuk 22 | https://www.youtube.com/watch?v=YcJTyrG3bZs 23 | 24 | https://leetcode.com/problems/decode-ways/description/ 25 | */ 26 | 27 | // O(N) DP 28 | var numDecodings = function(s) { 29 | if(!s || s.length === 0 || s[0] === '0') { 30 | return 0; 31 | } 32 | 33 | if(s.length === 1 && s[0] === '0') { 34 | return 0; 35 | } 36 | 37 | let n = s.length; 38 | let dp = new Array(n + 1).fill(0); 39 | dp[0] = 1; 40 | // Not zeros at the beginning are allowed 41 | dp[1] = s.charAt(1) != '0' ? 1 : 0; 42 | for (let i = 2; i <= s.length; i++) { 43 | let first = parseInt(s.substring(i - 1, i)); 44 | let second = parseInt(s.substring(i - 2, i)); 45 | if (first > 0 && first <= 9) { 46 | dp[i] = dp[i] + dp[i - 1]; 47 | } 48 | if (second >= 10 && second <= 26) { 49 | dp[i] = dp[i] + dp[i - 2]; 50 | } 51 | } 52 | return dp[n]; 53 | }; 54 | 55 | // Opción 2 56 | var numDecodings = function(s) { 57 | memo = {} 58 | return helper(s, s.length, memo); 59 | }; 60 | 61 | function helper(data, k, memo) { 62 | // Base case numDecodings("") = 1 63 | if(k === 0) { 64 | return 1; 65 | } 66 | 67 | let s = data.length - k; 68 | // Base case numDecodings("011") = 0 69 | if(data[s] === '0') { 70 | return 0; 71 | } 72 | 73 | // Save memoization 74 | if(memo[k]) { 75 | return memo[k]; 76 | } 77 | 78 | let result = helper(data, k-1, memo); 79 | if(k >= 2 && parseInt(data.substring(s,s+2)) <= 26) { 80 | result += helper(data, k-2, memo) 81 | } 82 | memo[k] = result 83 | return result; 84 | } 85 | 86 | // Opción 3 87 | var numDecodings = function(s) { 88 | let memo = new Array(s.length + 1).fill(-1); 89 | return helper(s, 0, memo); 90 | }; 91 | 92 | function helper(s, index, memo) { 93 | 94 | // Base case 1: our index get to the string so we can decode it 95 | if(index === s.length) { 96 | return 1; 97 | } 98 | 99 | // We already compute this value 100 | if(memo[index] > 0) { 101 | return memo[index]; 102 | } 103 | 104 | /* 105 | We don't already know the answer to this subproblem, calculate it 106 | by taking the sum of the total ways for a single character decoring 107 | or 2 character decoding 108 | */ 109 | let count = 0; 110 | 111 | // Just to be sabe - one character decoding 112 | if(index + 1 <= s.length) { 113 | let tmp = s.substring(index, index + 1); 114 | if(isValid(tmp)) { 115 | count += helper(s, index + 1, memo); 116 | } 117 | } 118 | 119 | // Just to be sabe - two characters decoding 120 | if(index + 2 <= s.length) { 121 | let tmp = s.substring(index, index + 2); 122 | if(isValid(tmp)) { 123 | count += helper(s, index + 2, memo); 124 | } 125 | } 126 | 127 | // Store the value of the subproblem 128 | memo[index] = count; 129 | 130 | return count; 131 | } 132 | 133 | function isValid(s) { 134 | if(!s) { 135 | return false; 136 | } 137 | 138 | if(s[0] === '0') { 139 | return false; 140 | } 141 | 142 | return parseInt(s) >= 1 && parseInt(s) <= 26; 143 | } 144 | 145 | str = "227"; 146 | console.log(numDecodings(str)); -------------------------------------------------------------------------------- /divide.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator. 3 | 4 | Return the quotient after dividing dividend by divisor. 5 | 6 | The integer division should truncate toward zero. 7 | 8 | Example 1: 9 | 10 | Input: dividend = 10, divisor = 3 11 | Output: 3 12 | Example 2: 13 | 14 | Input: dividend = 7, divisor = -3 15 | Output: -2 16 | Note: 17 | 18 | Both dividend and divisor will be 32-bit signed integers. 19 | The divisor will never be 0. 20 | Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows. 21 | 22 | https://leetcode.com/problems/divide-two-integers/description/ 23 | 24 | */ 25 | 26 | // Option 1 27 | // The implementation above is very inneficient especially when the 28 | // divisor is relative small compared to the dividend. Note that with 29 | // this solution, we deduct the divisor once a time. If we can deduct 30 | // the divisor in expotential rate, the algorithm will run much faster 31 | var divide = function(dividend, divisor){ 32 | // Edge cases 33 | if(dividend === 0) return 0; 34 | if(divisor === 0 && dividend > 0) return Number.MAX_SAFE_NUMBER; 35 | if(divisor === 0 && dividend < 0) return Number.MIN_SAFE_NUMBER; 36 | if(divisor === 1) return dividend; 37 | if(divisor === -1) return -dividend; 38 | 39 | // In JS all numbers are 64 bits floating, in other case here will be the conversion to long numbers 40 | let dividendL = dividend; 41 | let divisorL = divisor; 42 | 43 | let isDividendNegative = false; 44 | let isDivisorNegative = false; 45 | 46 | if(dividendL < 0) { 47 | isDividendNegative = true; 48 | } 49 | 50 | if(divisorL < 0) { 51 | isDivisorNegative = true; 52 | } 53 | 54 | let result = 0; 55 | while(dividendL > divisorL) { 56 | dividendL -= divisorL; 57 | result++; 58 | } 59 | 60 | if((!isDividendNegative && isDivisorNegative) || (isDivisorNegative && !isDivisorNegative)) { 61 | return -result; 62 | } 63 | 64 | return result; 65 | } 66 | 67 | var divide = function(dividend, divisor) { 68 | if(dividend === 0) return 0; 69 | 70 | let isNeg = false; 71 | if((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) { 72 | isNeg = true; 73 | } 74 | 75 | // In JS all numbers are 64 bits floating, in other case here will be the conversion to long numbers 76 | let dividendL = dividend; 77 | let divisorL = divisor; 78 | 79 | let result = 0; 80 | 81 | while(dividendL >= divisorL) { 82 | let shift = 0; 83 | // 2 << 0 = 2, 2 << 1 = 4, 2 << 2 = 8, 2 << 3 = 16, 2 << 4 = 32, 2 << 5 = 64 84 | while(dividendL >= (divisor << shift)) { 85 | shift++; 86 | } 87 | 88 | result += (1 << (shift - 1)); 89 | dividendL -= divisor << (shift - 1); 90 | } 91 | 92 | if (isNeg) return -result; 93 | return result; 94 | 95 | } 96 | 97 | // Accepted 98 | 99 | public int divide(int dividend, int divisor) { 100 | if (divisor == 0 || (dividend == Integer.MIN_VALUE && divisor == -1)) 101 | return Integer.MAX_VALUE; 102 | 103 | int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1; 104 | long dvd = Math.abs((long) dividend); 105 | long dvs = Math.abs((long) divisor); 106 | 107 | int res = 0; 108 | while (dvd >= dvs) { 109 | long temp = dvs, multiple = 1; 110 | while (dvd >= (temp << 1)) { 111 | temp = temp << 1; 112 | multiple = multiple << 1; 113 | } 114 | dvd = (int)(dvd - temp); 115 | res = (int)(res + multiple); 116 | } 117 | 118 | return sign == 1 ? res : -res; 119 | } 120 | 121 | 122 | 123 | dividend = 16; 124 | divisor = 3; 125 | console.log(divide(dividend, divisor)); -------------------------------------------------------------------------------- /findCelebrity.js: -------------------------------------------------------------------------------- 1 | /* 2 | In a party of N people, only one person is known to everyone. Such a person may be present in the party, if yes, (s)he doesn’t know anyone in the party. We can only ask questions like “does A know B? “. Find the stranger (celebrity) in minimum number of questions. 3 | 4 | We can describe the problem input as an array of numbers/characters representing persons in the party. We also have a hypothetical function HaveAcquaintance(A, B) which returns true if A knows B, false otherwise. How can we solve the problem. 5 | 6 | 7 | If A knows B, then A can’t be celebrity. Discard A, and B may be celebrity. 8 | If A doesn’t know B, then B can’t be celebrity. Discard B, and A may be celebrity. 9 | Repeat above two steps till we left with only one person. 10 | Ensure the remained person is celebrity. (Why do we need this step?) 11 | 12 | https://www.geeksforgeeks.org/the-celebrity-problem/ 13 | */ 14 | 15 | // Returns -1 if celebrity 16 | // is not present. If present, 17 | // returns id (value from 0 to n-1). 18 | var findCelebrity = function(n) { 19 | let stack = []; 20 | 21 | // Push everybody into the stack 22 | for(let i = 0; i < n; i++) { 23 | stack.push(i); 24 | } 25 | 26 | while(stack.length > 1) { 27 | let person1 = stack.pop(); 28 | let person2 = stack.pop(); 29 | 30 | if(knows(person1, person2)) { 31 | stack.push(person2); 32 | } else { 33 | stack.push(person1); 34 | } 35 | } 36 | 37 | console.log(stack) 38 | 39 | // At this point this is our candidate to be the celebrity as it´s the only one in the stack 40 | let celebrity = stack.pop(); 41 | 42 | // Verify if it´s a celebrity as all should know him. 43 | for(let i = 0; i < n; i++) { 44 | if(i !== celebrity && knows(celebrity,i) && !knows(i, celebrity)) { 45 | return -1; // There´s no celebrity 46 | } 47 | } 48 | 49 | return celebrity; 50 | 51 | }; 52 | 53 | /*Two pointers technique*/ 54 | var findCelebrity = function(n) { 55 | let start = 0; 56 | let end = n - 1; 57 | 58 | while(start < end) { 59 | if(knows(start, end)) { 60 | start++; 61 | } else { 62 | end--; 63 | } 64 | } 65 | 66 | // start is our celebrity candidate 67 | for(let i = 0; i < n; i++) { 68 | if(i !== start && (knows(start,i) || !knows(i,start))) { 69 | return -1; 70 | } 71 | } 72 | 73 | // start is the celebrity 74 | return start; 75 | 76 | }; 77 | 78 | // Returns true if a knows 79 | // b, false otherwise 80 | function knows(a, b) { 81 | return PERSON[a][b] == 1 ? true : false; 82 | } 83 | 84 | // Person with 2 is celebrity 85 | PERSON = [ 86 | [0, 0, 1, 0 ], 87 | [0, 0, 1, 0 ], 88 | [0, 0, 0, 0 ], 89 | [0, 0, 1, 0 ] 90 | ]; 91 | 92 | n = 4; 93 | console.log(findCelebrity(n)); 94 | -------------------------------------------------------------------------------- /findClosestBST.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary search tree and a target node K. The task is to find the node with minimum absolute difference with given target value K. 3 | 4 | https://www.geeksforgeeks.org/find-closest-element-binary-search-tree/ 5 | */ 6 | 7 | function TreeNode(val, left, right) { 8 | this.val = val; 9 | this.left = left || null; 10 | this.right = right || null; 11 | } 12 | 13 | 14 | // Opción 1 (Use benefit of BST properties) 15 | function findDiff(node, n) { 16 | let minDiff = Number.MAX_SAFE_INTEGER; 17 | let result = {num: 0}; 18 | 19 | helper(node, minDiff, result, n); 20 | return result.num; 21 | } 22 | 23 | function helper(node, minDiff, result, n) { 24 | // Base case 25 | if(!node) { 26 | return; 27 | } 28 | 29 | if(node.val === n) { 30 | result.num = 0; 31 | return; 32 | } 33 | 34 | if(minDiff > Math.abs(n - node.val)) { 35 | minDiff = Math.abs(n - node.val); 36 | result.num = node.val; 37 | } 38 | 39 | if(n < node.val) { 40 | helper(node.left, minDiff, result, n); 41 | } else { 42 | helper(node.right, minDiff, result, n); 43 | } 44 | } 45 | 46 | // Opción 2 47 | // Time O(h) 48 | // Space O(N) 49 | function findDiff(node,n) { 50 | let array = []; 51 | inorder(node, array) 52 | 53 | let minDiff = Number.MAX_SAFE_INTEGER; 54 | let result = 0; 55 | 56 | for(let i = 0; i < array.length; i++) { 57 | if(minDiff > Math.abs(n - array[i])) { 58 | minDiff = Math.abs(n - array[i]); 59 | result = array[i]; 60 | } 61 | } 62 | 63 | return result; 64 | } 65 | 66 | function inorder(node, array) { 67 | if(!node) return; 68 | 69 | inorder(node.left, array); 70 | array.push(node.val); 71 | inorder(node.right, array); 72 | } 73 | 74 | /* 75 | 9 76 | 4 17 77 | 3 6 22 78 | 5 7 20 79 | */ 80 | tree = new TreeNode(9, new TreeNode(4, new TreeNode(3), new TreeNode(6, new TreeNode(5), new TreeNode(7))), new TreeNode(17, null, new TreeNode(22, new TreeNode(20)))); 81 | n = 8; 82 | console.log(findDiff(tree, n)); -------------------------------------------------------------------------------- /findDisappearedNumbers.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. 3 | 4 | Find all the elements of [1, n] inclusive that do not appear in this array. 5 | 6 | Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space. 7 | 8 | Example: 9 | 10 | Input: 11 | [4,3,2,7,8,2,3,1] 12 | 13 | Output: 14 | [5,6] 15 | 16 | https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/ 17 | 18 | */ 19 | 20 | var findDisappearedNumbers = function(nums) { 21 | let result = []; 22 | 23 | if(!nums.length) { 24 | return []; 25 | } 26 | 27 | for(let i = 0; i < nums.length; i++) { 28 | // Get the index 0-based 29 | let index = Math.abs(nums[i]) - 1; 30 | 31 | // If the number is negative it means that the number 32 | // has been found. 33 | // Marcamos con negativo los números de los indices que 34 | // vayamos encontrando 35 | if (nums[index] > 0) { 36 | nums[index] = -nums[index]; 37 | } 38 | } 39 | 40 | // The positive numbers are those that were not found 41 | for(let i = 0; i < nums.length; i++) { 42 | if(nums[i] > 0) { 43 | result.push(i + 1); 44 | } 45 | } 46 | 47 | console.log(nums); 48 | return result; 49 | }; 50 | 51 | // Time O(n) 52 | // Space O(n) 53 | var findDisappearedNumbers = function(nums) { 54 | let hash = {}; 55 | let result = []; 56 | 57 | if(!nums.length) { 58 | return result; 59 | } 60 | 61 | for(let i = 0; i < nums.length; i++) { 62 | if(!(nums[i] in hash)) { 63 | hash[nums[i]] = true; 64 | } 65 | } 66 | 67 | for(let i = 1; i <= nums.length; i++) { 68 | if(!(i in hash)) { 69 | result.push(i); 70 | } 71 | } 72 | 73 | return result; 74 | }; -------------------------------------------------------------------------------- /findKSmallestBST.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. 3 | 4 | Note: 5 | You may assume k is always valid, 1 ≤ k ≤ BST's total elements. 6 | 7 | Follow up: 8 | What if the BST is modified (insert/delete operations) often and you 9 | need to find the kth smallest frequently? How would you optimize the kthSmallest routine? 10 | 11 | https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/ 12 | */ 13 | 14 | function Node(val,left,right){ 15 | this.val = val; 16 | this.left = left || null; 17 | this.right = right || null; 18 | } 19 | 20 | /*Complejidad O(N)*/ 21 | function findKSmallestBST(tree, k){ 22 | let stack = []; 23 | let node = tree; 24 | let count = 0; 25 | let right; 26 | 27 | while(node){ 28 | stack.push(node); 29 | node = node.left; 30 | } 31 | 32 | while(stack.length > 0){ 33 | node = stack.pop(); 34 | count++; 35 | if(count === k){ 36 | return node.val; 37 | } 38 | right = node.right; 39 | while(right){ 40 | stack.push(right); 41 | right = right.left; 42 | } 43 | } 44 | return -1; 45 | } 46 | 47 | // Recursion with O(N) in space 48 | 49 | var kthSmallest = function(root, k) { 50 | let sorted = []; 51 | inorder(root, sorted); 52 | return sorted[k-1]; 53 | }; 54 | 55 | function inorder(node, sorted) { 56 | if(!node) return; 57 | inorder(node.left, sorted); 58 | sorted.push(node.val); 59 | inorder(node.right, sorted); 60 | } 61 | 62 | // Recursion with constant space 63 | 64 | var kthSmallest = function(root, k) { 65 | count = k; 66 | result = null; 67 | inorder(root); 68 | return result; 69 | }; 70 | 71 | function inorder(node) { 72 | if(!node) return; 73 | inorder(node.left); 74 | 75 | count--; 76 | if(count===0) { 77 | result = node.val; 78 | return; 79 | } 80 | 81 | inorder(node.right); 82 | } 83 | 84 | // Iterative 85 | 86 | var kthSmallest = function(root, k) { 87 | let stack = []; 88 | let node = root; 89 | while(true) { 90 | if(node !== null) { 91 | stack.push(node); 92 | node = node.left; 93 | } else { 94 | // No more elements in the stack 95 | if(stack.length === 0) { 96 | break; 97 | } 98 | node = stack.pop(); 99 | --k; 100 | if(k === 0) { 101 | return node.val; 102 | } 103 | stack.push(node.right); 104 | } 105 | } 106 | 107 | // Element not found 108 | return -1; 109 | }; 110 | 111 | 112 | tree = new Node(7, new Node(5, new Node(4, new Node(3)), new Node(6)), new Node(10, new Node(9), new Node(11))); 113 | k = 4; 114 | console.log(findKSmallestBST(tree,k)); -------------------------------------------------------------------------------- /findKthLargestInArray.js: -------------------------------------------------------------------------------- 1 | /* 2 | Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. 3 | 4 | Example 1: 5 | 6 | Input: [3,2,1,5,6,4] and k = 2 7 | Output: 5 8 | Example 2: 9 | 10 | Input: [3,2,3,1,2,4,5,5,6] and k = 4 11 | Output: 4 12 | Note: 13 | You may assume k is always valid, 1 ≤ k ≤ array's length. 14 | 15 | https://leetcode.com/problems/kth-largest-element-in-an-array/description/ 16 | */ 17 | 18 | // Quick Select 19 | //O(N) best case, worst O(N^2) 20 | var findKthLargest = function(nums, k) { 21 | let left = 0; 22 | let right = nums.length - 1; 23 | // Para sacar el kth smallest es k = nums.length - k * 1 24 | while (true) { // this problem guaranteed to have a valid answer 25 | let pos = partition(nums, left, right); 26 | if (pos == k - 1) return nums[pos]; 27 | else if (pos < k - 1) left = pos + 1; 28 | else right = pos - 1; 29 | } 30 | }; 31 | 32 | // take pivot, put elements smaller on the left, larger on right 33 | function partition(nums, left, right) { 34 | let pivot = nums[left]; 35 | let idx = left; 36 | swap(nums, idx, right); 37 | for (let i = left; i < right; i++) 38 | if (nums[i] > pivot) swap(nums, i, idx++); 39 | swap(nums, idx, right); 40 | return idx; 41 | } 42 | 43 | function swap(nums, i, j) { 44 | let tmp = nums[i]; 45 | nums[i] = nums[j]; 46 | nums[j] = tmp; 47 | } 48 | 49 | 50 | // O(NlogN) 51 | var findKthLargest = function(nums, k) { 52 | let sortedArray = nums.sort((a,b) => b-a ); 53 | return sortedArray[k-1]; 54 | }; 55 | 56 | //O(NlogK) 57 | class Solution { 58 | public int findKthLargest(int[] nums, int k) { 59 | PriorityQueue largeK = new PriorityQueue(k + 1); 60 | 61 | for(int el : nums) { 62 | largeK.add(el); 63 | if (largeK.size() > k) { 64 | largeK.poll(); 65 | } 66 | } 67 | 68 | return largeK.poll(); 69 | } 70 | } -------------------------------------------------------------------------------- /findMedian.java: -------------------------------------------------------------------------------- 1 | /* 2 | Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. 3 | 4 | For example, 5 | [2,3,4], the median is 3 6 | 7 | [2,3], the median is (2 + 3) / 2 = 2.5 8 | 9 | Design a data structure that supports the following two operations: 10 | 11 | void addNum(int num) - Add a integer number from the data stream to the data structure. 12 | double findMedian() - Return the median of all elements so far. 13 | 14 | https://leetcode.com/problems/find-median-from-data-stream/description/ 15 | 16 | Example: 17 | 18 | addNum(1) 19 | addNum(2) 20 | findMedian() -> 1.5 21 | addNum(3) 22 | findMedian() -> 2 23 | 24 | 25 | Follow up: 26 | 27 | If all integer numbers from the stream are between 0 and 100, how would you optimize it? 28 | If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it? 29 | */ 30 | 31 | import java.io.*; 32 | import java.util.*; 33 | import java.text.*; 34 | import java.math.*; 35 | import java.util.regex.*; 36 | 37 | public class MedianFinder { 38 | PriorityQueue minHeap; // larger part 39 | PriorityQueue maxHeap; // smaller part 40 | 41 | public MedianFinder() { 42 | minHeap = new PriorityQueue<>(); 43 | maxHeap = new PriorityQueue<>(new Comparator(){ 44 | public int compare(Integer i1, Integer i2) { 45 | return i2 - i1; 46 | } 47 | }); 48 | } 49 | // Adds a number into the data structure. 50 | public void addNum(int num) { 51 | minHeap.offer(num); 52 | maxHeap.offer(minHeap.poll()); 53 | if (minHeap.size() < maxHeap.size()) 54 | minHeap.offer(maxHeap.poll()); 55 | } 56 | // Returns the median of current data stream 57 | public double findMedian() { 58 | return minHeap.size() > maxHeap.size() ? minHeap.peek() : (maxHeap.peek() + minHeap.peek()) / 2.0; 59 | } 60 | } 61 | 62 | /** 63 | * Your MedianFinder object will be instantiated and called as such: 64 | * MedianFinder obj = new MedianFinder(); 65 | * obj.addNum(num); 66 | * double param_2 = obj.findMedian(); 67 | */ -------------------------------------------------------------------------------- /findShortestPathBFS.js: -------------------------------------------------------------------------------- 1 | /* 2 | Shortest distance between two cells in a matrix or grid 3 | Given a matrix of N*M order. Find the shortest distance from a source cell to a destination cell, traversing through limited cells only. Also you can move only up, down, left and right. If found output the distance else -1. 4 | s represents ‘source’ 5 | d represents ‘destination’ 6 | * represents cell you can travel 7 | 0 represents cell you can not travel 8 | This problem is meant for single source and destination. 9 | 10 | 11 | https://www.geeksforgeeks.org/shortest-distance-two-cells-matrix-grid/ 12 | */ 13 | 14 | function Item(row, col, distance) { 15 | this.row = row || null; 16 | this.col = col || null; 17 | this.distance = distance || 0; 18 | } 19 | 20 | function findShortestPath(grid) { 21 | 22 | let ROW = grid.length; 23 | let COL = grid[0].length; 24 | let visited = []; 25 | 26 | // Form our visited matrix 27 | for(let i = 0; i < ROW; i++) { 28 | visited[i] = new Array(COL).fill(false); 29 | } 30 | 31 | let source = new Item(); 32 | 33 | for(let i = 0 ; i < ROW; i++) { 34 | for(let j = 0; j < COL; j++) { 35 | if(grid[i][j] === '0') { 36 | visited[i][j] = -1; 37 | } else { 38 | visited[i][j] = 0; 39 | } 40 | 41 | // Find the source 42 | if(grid[i][j] === 's') { 43 | source.row = i; 44 | source.col = j; 45 | } 46 | } 47 | } 48 | 49 | // Apply BFS on matrix cell starting from source 50 | let queue = []; 51 | queue.push(source); 52 | visited[source.row][source.col] = 0; 53 | 54 | // Move left, up, right, down 55 | let rowK = [0, -1, 0, 1]; 56 | let colK = [-1, 0, 1, 0]; 57 | 58 | while(queue.length) { 59 | let item = queue.shift(); 60 | let row = item.row; 61 | let col = item.col; 62 | 63 | for(let i = 0; i < 4; i++) { 64 | let rowNext = row + rowK[i]; 65 | let colNext = col + colK[i]; 66 | 67 | if(isSafe(grid, visited, rowNext, colNext)) { 68 | 69 | if(grid[rowNext][colNext] === 'd') { 70 | return item.distance + 1; 71 | } 72 | // Where we come + 1 as is a new step 73 | visited[rowNext][colNext] = visited[row][col] + 1; 74 | // distance has the updated number 75 | let distance = visited[rowNext][colNext]; 76 | // Mark as visited in the grid 77 | grid[rowNext][colNext] = 'V' 78 | queue.push(new Item(rowNext, colNext, distance)); 79 | } 80 | } 81 | } 82 | 83 | console.log(grid); 84 | console.log(source); 85 | return visited; 86 | } 87 | 88 | function isSafe(grid,visited,row,col){ 89 | let ROW = grid.length; 90 | let COL = grid[0].length; 91 | return ( 92 | (row >= 0 && row < ROW) && 93 | (col >= 0 && col < COL) && 94 | // To me available spaces or destination 95 | (grid[row][col] === '*' || grid[row][col] === 'd') && 96 | // We have not visited yet 97 | visited[row][col] !== -1 98 | ); 99 | } 100 | 101 | // 0 - wall 102 | // * - free, can move 103 | // s - source 104 | // d - destination 105 | grid = [ 106 | ['0', '*', '0', 's'], 107 | ['*', '0', '*', '*'], 108 | ['0', '*', '*', '*'], 109 | ['d', '*', '*', '*'] 110 | ]; 111 | console.log(findShortestPath(grid)); -------------------------------------------------------------------------------- /graphValidTree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given n nodes labeled from 0 to n-1 and a list of undirected edges (each edge is a pair of nodes), write 3 | a function to check whether these edges make up a valid tree. 4 | 5 | For example 6 | 7 | Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true. 8 | Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false. 9 | 10 | You can assume that no duplicates edges will appear in edges. Since all edges are undirected [0, 1] is the 11 | same as [1, 0] and thus will not appear together in edges. 12 | 13 | https://leetcode.com/problems/graph-valid-tree/ 14 | 15 | https://www.youtube.com/watch?v=n_t0a_8H8VY 16 | https://www.youtube.com/watch?v=rFf4mXWbb9U 17 | https://www.youtube.com/watch?v=ojge0iS19qQ 18 | https://www.programcreek.com/2014/05/graph-valid-tree-java/ 19 | https://www.youtube.com/watch?v=vsIb9B84Rt8 20 | 21 | Para ser un árbol válido debe estar conectado y no debe haber ciclos 22 | 23 | 24 | Time: O(V) - V number of vertices 25 | Space: O(V) 26 | */ 27 | 28 | var validTree = function(n, edges) { 29 | 30 | // Corner case 31 | if(edges.length !== n-1) return false; 32 | 33 | let graph = []; 34 | 35 | // Create the graph 36 | for(let i = 0; i < n; i++) { 37 | graph[i] = []; 38 | } 39 | 40 | // Fill the undirected graph 41 | for(let i = 0; i < edges.length; i++) { 42 | // Destructuring 43 | // Insert both sides as the graph is undirected 44 | let [from, to] = edges[i]; 45 | graph[from].push(to); 46 | graph[to].push(from); 47 | } 48 | 49 | // Visited edges 50 | let visited = new Array(n).fill(0); 51 | 52 | // Visit the first node 53 | visited[0] = true; 54 | // Check that there is no cycle 55 | if(dfs(graph, visited, 0, -1)) { 56 | return false; 57 | } 58 | 59 | // Check if all the graph is connected 60 | for(let i = 0; i < visited.length; i++) { 61 | if(!visited[i]) { 62 | return false; 63 | } 64 | } 65 | 66 | // All the graph is connected and there is no cycle at this point 67 | return true; 68 | } 69 | 70 | // Has cycle 71 | function dfs(graph, visited, node, parent) { 72 | 73 | let sub = graph[node]; 74 | for(let i = 0; i < sub.length; i++) { 75 | let v = sub[i]; 76 | // Ignore if the node is coming from the father i.e [1,0], [0, 1] 77 | if(v === parent) continue; 78 | if(!visited[v]) { 79 | visited[v] = true; 80 | return dfs(graph, visited, v, node); 81 | } else { 82 | // The node has been visited 83 | return true; 84 | } 85 | } 86 | // The node has not been visited 87 | return false; 88 | } 89 | 90 | n = 5; 91 | // edges = [[0, 1], [0, 2], [0, 3], [1, 4]]; 92 | edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]]; 93 | console.log(validTree(n, edges)); 94 | -------------------------------------------------------------------------------- /groupAnagrams.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of strings, group anagrams together. 3 | 4 | For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"], 5 | Return: 6 | 7 | [ 8 | ["ate", "eat","tea"], 9 | ["nat","tan"], 10 | ["bat"] 11 | ] 12 | Note: All inputs will be in lower-case. 13 | 14 | https://leetcode.com/problems/group-anagrams/description/ 15 | */ 16 | 17 | /** 18 | * @param {string[]} strs 19 | * @return {string[][]} 20 | */ 21 | var groupAnagrams = function(strs) { 22 | var map = {}; 23 | var result = []; 24 | strs.forEach((word, index) => { 25 | let sortWord = sortedWord(word); 26 | if(sortWord in map){ 27 | map[sortWord].push(word); 28 | }else{ 29 | map[sortWord] = [word]; 30 | } 31 | }); 32 | //console.log(map); 33 | //Format output 34 | for(let prop in map){ 35 | result.push(map[prop]); 36 | } 37 | return result; 38 | }; 39 | 40 | const sortedWord = word => word.split('').sort().join(''); 41 | 42 | array = ["eat", "tea", "tan", "ate", "nat", "bat"]; 43 | console.log(groupAnagrams(array)); -------------------------------------------------------------------------------- /groupSumRecursion.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://codingbat.com/prob/p145416 3 | 4 | Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target? This is a classic backtracking recursion problem. Once you understand the recursive backtracking strategy in this problem, you can use the same pattern for many problems to search a space of choices. Rather than looking at the whole array, our convention is to consider the part of the array starting at index start and continuing to the end of the array. The caller can specify the whole array simply by passing start as 0. No loops are needed -- the recursive calls progress down the array. 5 | 6 | groupSum(0, [2, 4, 8], 10) → true 7 | groupSum(0, [2, 4, 8], 14) → true 8 | groupSum(0, [2, 4, 8], 9) → false 9 | */ 10 | 11 | 12 | public boolean groupSum(int start, int[] nums, int target) { 13 | // Base case 14 | if(target == 0) { 15 | return true; 16 | } 17 | 18 | if(start >= nums.length || target < 0){ 19 | return false; 20 | } 21 | 22 | // Analizamos los dos caminos, considerando el número y no considerando el camino. 23 | return groupSum(start + 1, nums, target - nums[start]) || groupSum(start + 1, nums, target); 24 | } -------------------------------------------------------------------------------- /invertTree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Invert a binary tree. 3 | 4 4 | / \ 5 | 2 7 6 | / \ / \ 7 | 1 3 6 9 8 | to 9 | 4 10 | / \ 11 | 7 2 12 | / \ / \ 13 | 9 6 3 1 14 | https://leetcode.com/problems/invert-binary-tree/description/ 15 | */ 16 | 17 | function TreeNode(val, left, right) { 18 | this.val = val; 19 | this.left = left || null; 20 | this.right = right || null; 21 | } 22 | 23 | // Recursion 24 | var invertTree = function(root) { 25 | if (!root) { 26 | return null; 27 | } 28 | let left = invertTree(root.left); 29 | let right = invertTree(root.right); 30 | root.left = right; 31 | root.right = left; 32 | return root; 33 | }; 34 | 35 | // Iterative BFS 36 | var invertTree = function(root) { 37 | if (!root) { 38 | return null; 39 | } 40 | let queue = []; 41 | queue.push(root); 42 | 43 | while(queue.length) { 44 | let len = queue.length; 45 | for (let i = 0; i < len; i++) { 46 | let node = queue.shift(); 47 | let left = node.left; 48 | let right = node.right; 49 | // Invert 50 | node.left = right; 51 | node.right = left; 52 | if (node.left) { 53 | queue.push(node.left); 54 | } 55 | 56 | if (node.right) { 57 | queue.push(node.right); 58 | } 59 | } 60 | } 61 | return root; 62 | }; 63 | 64 | tree = new TreeNode(4, new TreeNode(2, new TreeNode(1), new TreeNode(3)), new TreeNode(7, new TreeNode(6), new TreeNode(9))); 65 | //tree = new TreeNode(1,new TreeNode(2)); 66 | console.log(invertTree(tree)); 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /isMatch.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Implement regular expression matching with support for '.' and '*'. 4 | 5 | '.' Matches any single character. 6 | '*' Matches zero or more of the preceding element. 7 | 8 | The matching should cover the entire input string (not partial). 9 | 10 | The function prototype should be: 11 | bool isMatch(const char *s, const char *p) 12 | 13 | Some examples: 14 | isMatch("aa","a") → false 15 | isMatch("aa","aa") → true 16 | isMatch("aaa","aa") → false 17 | isMatch("aa", "a*") → true 18 | isMatch("aa", ".*") → true 19 | isMatch("ab", ".*") → true 20 | isMatch("aab", "c*a*b") → true 21 | 22 | https://leetcode.com/problems/regular-expression-matching/#/description 23 | 24 | */ 25 | 26 | var isMatch = function(s, p) { 27 | var lenS = s.length, 28 | lenP = p.length; 29 | 30 | if (p.length === 0) { 31 | /*Aquí vamos a determinar si ambos son vacios que significa true, de lo contrario si "s" es mayor a cero y "p" que es 32 | nuestra regex no, es mayor a cero, significa que no hemos hecho match*/ 33 | return s.length === 0; 34 | } 35 | 36 | //Vamos a verificar si nuestro segundo caracter es "*" 37 | if (p.charAt(1) === '*') { 38 | /*Volveremos a llamar la función recursiva quitando el regex por ejemplo c*, si quitando el caracter tiene 39 | la misma letra inicial o el punto, podemos recortar ambas cadenas, eso va a pasar en el else de abajo, si no 40 | tienen las mismas cadenas, vamos a eliminar la primer letra de nuestra "s" que es nuestra cadena original, esto 41 | es porque podemos tener ninguna o muchas repeticiones y las iremos elimando hasta que podamos verificar si hace 42 | match o no */ 43 | return isMatch(s, p.substr(2)) || s.length > 0 && (s.charAt(0) === p.charAt(0) || p.charAt(0) === '.') && isMatch(s.substr(1), p); 44 | } else { 45 | /*if s.length - falsy (evaluado a false en boolean) regresa false, de lo contrario verifica la cadena 46 | (s.charAt(0) === p.charAt(0) || p.charAt(0) === '.') y si es true regresa isMatch(s.substr(1), p.substr(1)) 47 | */ 48 | /*return a && b means 49 | if (a) return b; 50 | else return a; 51 | */ 52 | return s.length > 0 && (s.charAt(0) === p.charAt(0) || p.charAt(0) === '.') && isMatch(s.substr(1), p.substr(1)); 53 | } 54 | 55 | }; 56 | 57 | /* 58 | https://www.youtube.com/watch?v=l3hda49XcDE 59 | */ 60 | 61 | /** 62 | * @param {string} s 63 | * @param {string} p 64 | * @return {boolean} 65 | */ 66 | var isMatch = function(s, p) { 67 | // s = string, p = pattern 68 | let dp = new Array(s.length+1); 69 | for(let i = 0; i < dp.length; i++) { 70 | dp[i] = new Array(p.length+1).fill(false); 71 | } 72 | 73 | // In case there's empty string for s and p 74 | dp[0][0] = true; 75 | 76 | //Deal with column 0 cases for patterns like a*, a*b* or a*b*c* 77 | // To set true or false for the first column 78 | for(let i = 1; i < dp[0].length; i++){ 79 | if(p[i-1] === '*') { 80 | dp[0][i] = dp[0][i-2]; 81 | } 82 | } 83 | 84 | for(let i = 1; i < dp.length; i++) { 85 | for(let j = 1; j < dp[0].length; j++) { 86 | if(p[j-1] === '.' || p[j-1] === s[i-1]) { 87 | dp[i][j] = dp[i-1][j-1]; 88 | }else if(p[j-1] === '*') { 89 | dp[i][j] = dp[i][j-2]; 90 | if(p[j-2] === '.' || p[j-2] === s[i-1]){ 91 | dp[i][j] = dp[i][j] || dp[i-1][j]; 92 | } 93 | }else { 94 | dp[i][j] = false; 95 | } 96 | } 97 | } 98 | 99 | return dp[s.length][p.length] 100 | }; 101 | 102 | s = "aab"; 103 | p = "c*a*b"; 104 | console.log(isMatch(s,p)); 105 | -------------------------------------------------------------------------------- /isValidBST.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, determine if it is a valid binary search tree (BST). 3 | 4 | Assume a BST is defined as follows: 5 | 6 | The left subtree of a node contains only nodes with keys less than the node's key. 7 | The right subtree of a node contains only nodes with keys greater than the node's key. 8 | Both the left and right subtrees must also be binary search trees. 9 | Example 1: 10 | 2 11 | / \ 12 | 1 3 13 | Binary tree [2,1,3], return true. 14 | Example 2: 15 | 1 16 | / \ 17 | 2 3 18 | Binary tree [1,2,3], return false. 19 | 20 | https://leetcode.com/problems/validate-binary-search-tree/description/ 21 | */ 22 | 23 | //Option 1 24 | 25 | function Tree(val, left, right){ 26 | this.val = val; 27 | this.left = left || null; 28 | this.right = right || null; 29 | } 30 | 31 | var isValidBST = function(root) { 32 | return checkBST(root, Number.MAX_SAFE_VALUE, Number.MIN_SAFE_VALUE); 33 | }; 34 | 35 | function checkBST(node, MIN, MAX){ 36 | if(node === null) return true; 37 | if(node.val <= MIN || node.val >= MAX) return false; 38 | return checkBST(node.left, MIN, node.val) && checkBST(node.right, node.val, MAX); 39 | } 40 | 41 | // Option 2 42 | 43 | // Walk inorder + prev value 44 | let prev = null; 45 | var isValidBST = function(root) { 46 | // Base case 47 | if(!root) return true; 48 | 49 | // Left 50 | if(root.left) { 51 | if(!isValidBST(root.left)) return false; 52 | } 53 | 54 | // Action 55 | if(prev !== null && prev >= root.val) { 56 | return false; 57 | } 58 | 59 | // Right 60 | if(root.right) { 61 | if(!isValidBST(root.right)) return false; 62 | } 63 | 64 | return true; 65 | 66 | }; 67 | 68 | tree = new Tree(1,new Tree(1)); 69 | console.log(isValidBST(tree)); -------------------------------------------------------------------------------- /letterCombinations.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a digit string, return all possible letter combinations that the number could represent. 3 | 4 | A mapping of digit to letters (just like on the telephone buttons) is given below. 5 | 6 | https://leetcode.com/problems/letter-combinations-of-a-phone-number/#/description 7 | */ 8 | 9 | var letterCombinations = function(digits) { 10 | // Para matcharlo con los elementos exactos sin tener que hacer alguna otra operación 11 | let map = ['0', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']; 12 | let result = []; 13 | 14 | if(digits.length === 0) return [] 15 | 16 | combinations(result, '', map, digits, 0); 17 | return result; 18 | }; 19 | 20 | function combinations(result, tmp, map, digits, count){ 21 | if(count === digits.length) { 22 | result.push(tmp); 23 | return; 24 | } 25 | 26 | for(let i = 0; i < map[(digits[count]) * 1].length; i++) { // *1 will make it number 27 | combinations(result, tmp + map[(digits[count]) * 1].charAt(i), map, digits, count + 1) 28 | } 29 | } 30 | 31 | 32 | 33 | var letterCombinations = function(digits) { 34 | var length = digits.length; 35 | var hash = { 36 | '1' : '', 37 | '2' : ['a', 'b', 'c'], 38 | '3' : ['d', 'e', 'f'], 39 | '4' : ['g', 'h', 'i'], 40 | '5' : ['j', 'k', 'l'], 41 | '6' : ['m', 'n', 'o'], 42 | '7' : ['p', 'q', 'r', 's'], 43 | '8' : ['t', 'u', 'v'], 44 | '9' : ['w', 'x', 'y', 'z'] 45 | } 46 | if(digits.length === 0) return []; 47 | return combineLettersKey([''], 0, length, digits, hash); 48 | }; 49 | 50 | function combineLettersKey(currentCombinations, index, length, digits, hash){ 51 | var next = []; 52 | var tmp = ''; 53 | if(index === length) return currentCombinations; 54 | //Iteramos hasta el arreglo en donde vamos metiendo todas las combinaciones, ahí iremos concatenando todo 55 | //Nuestro arreglo de combinaciones lo usamos para meter todo concatenando con lo nuevo de los digitos 56 | for(var i = 0; i < currentCombinations.length; i++){ 57 | for(var j = 0; j < hash[digits.charAt(index)].length; j++){ 58 | tmp = currentCombinations[i] + hash[digits.charAt(index)][j]; 59 | next.push(tmp); 60 | } 61 | } 62 | return combineLettersKey(next, index+1, length, digits, hash); 63 | } 64 | 65 | digits = "23"; 66 | console.log(letterCombinations(digits)); -------------------------------------------------------------------------------- /longestArithmeticProgressionSubsequence.js: -------------------------------------------------------------------------------- 1 | // We can solve this problem in O(n2) time using Dynamic Programming. To get idea of the DP solution, let us first discuss solution of following simpler problem. 2 | 3 | // Given a sorted set, find if there exist three elements in Arithmetic Progression or not 4 | // Please note that, the answer is true if there are 3 or more elements in AP, otherwise false. 5 | // To find the three elements, we first fix an element as middle element and search for other two (one smaller and one greater). 6 | // We start from the second element and fix every element as middle element. For an element set[j] to be middle of AP, 7 | // there must exist elements ‘set[i]’ and ‘set[k]’ such that set[i] + set[k] = 2*set[j] where 0 <= i < j and j < k <=n-1. 8 | // How to efficiently find i and k for a given j? We can find i and k in linear time using following simple algorithm. 9 | // 1) Initialize i as j-1 and k as j+1 10 | // 2) Do following while i >= 0 and j <= n-1 ......... 11 | // a) If set[i] + set[k] is equal to 2*set[j], then we are done. 12 | // b) If set[i] + set[k] > 2*set[j], then decrement i (do i–-). 13 | // c) Else if set[i] + set[k] < 2*set[j], then increment k (do k++). 14 | 15 | // How to extend the above solution for the original problem? 16 | // The above function returns a boolean value. The required output of original problem is Length of the Longest Arithmetic Progression (LLAP) which is an integer value. 17 | // If the given set has two or more elements, then the value of LLAP is at least 2 (Why?). 18 | 19 | // The idea is to create a 2D table L[n][n]. An entry L[i][j] in this table stores LLAP with set[i] and set[j] as first two elements of AP and j > i. 20 | // The last column of the table is always 2 (Why – see the meaning of L[i][j]). Rest of the table is filled from bottom right to top left. 21 | // To fill rest of the table, j (second element in AP) is first fixed. i and k are searched for a fixed j. 22 | // If i and k are found such that i, j, k form an AP, then the value of L[i][j] is set as L[j][k] + 1. 23 | // Note that the value of L[j][k] must have been filled before as the loop traverses from right to left columns. 24 | 25 | // Reference: https://www.geeksforgeeks.org/longest-arithmetic-progression-dp-35/ 26 | // https://en.wikipedia.org/wiki/Arithmetic_progression 27 | 28 | // Time Complexity O(N^2) 29 | // Space Complexity O(N^2) 30 | var longestArithmeticSubsequence = function(nums) { 31 | if(nums.length < 3) { 32 | return nums.length; 33 | } 34 | 35 | let max = 2; 36 | let n = array.length; 37 | 38 | nums.sort((a,b) => a - b); // We need to have the numbers sorted 39 | 40 | // Create the table 41 | let dp = new Array(n); 42 | for(let i = 0; i < dp.length; i++) { 43 | dp[i] = new Array(dp.length).fill(0); 44 | } 45 | 46 | // initialize dp[i][n - 1] = 2 47 | for(let i = 0; i < n; i++) { 48 | dp[i][n-1] = 2; 49 | } 50 | 51 | // fix j (consider every nums[j] as second element of AP) to search for valid i & k 52 | for (let j = n - 2; j >= 1; j--) { 53 | let i = j - 1, k = j + 1; 54 | while (i >= 0 && k < n) { 55 | if (nums[i] + nums[k] < 2 * nums[j]) { 56 | k++; 57 | } else if (nums[i] + nums[k] > 2 * nums[j]) { 58 | dp[i][j] = 2; 59 | i--; 60 | } else { 61 | dp[i][j] = dp[j][k] + 1; 62 | max = Math.max(max, dp[i][j]); 63 | i--; 64 | k++; 65 | } 66 | } 67 | // If the loop was stopped due to k becoming more than n-1, set the remaining entties in column j as 2 68 | while (i >= 0) dp[i--][j] = 2; 69 | } 70 | return max; 71 | } 72 | 73 | // array = [1, 7, 10, 15, 27, 29]; // output = 3 74 | // The longest arithmetic progression is {1, 15, 29} 75 | 76 | 77 | array = [5, 10, 15, 20, 25, 30]; 78 | // output = 6 79 | 80 | console.log(longestArithmeticSubsequence(array)); -------------------------------------------------------------------------------- /longestCommonSubsequence.js: -------------------------------------------------------------------------------- 1 | // Dynamic Programming 2 | // Reference: https://www.youtube.com/watch?v=NnD96abizww 3 | // https://github.com/mission-peace/interview/blob/master/src/com/interview/dynamic/LongestCommonSubsequence.java 4 | var longestCommonSubsequence = function(str1, str2) { 5 | let dp = new Array(str1.length + 1); 6 | let max = 0; 7 | 8 | // Create our dp table 9 | for(let i = 0; i < dp.length; i++) { 10 | dp[i] = new Array(str2.length + 1).fill(0); 11 | } 12 | 13 | for(let i = 1; i < dp.length; i++) { 14 | for(let j = 1; j < dp[i].length; j++) { 15 | if(str1[i-1] === str2[j-1]) { 16 | dp[i][j] = dp[i-1][j-1] + 1; 17 | } else { 18 | dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); 19 | } 20 | if(dp[i][j] > max) { 21 | max = dp[i][j]; 22 | } 23 | } 24 | } 25 | console.log(dp); 26 | return max; 27 | } 28 | 29 | str1 = "abcdaf"; 30 | str2 = "acbcf"; 31 | // Result abcf, length = 4 32 | console.log(longestCommonSubsequence(str1, str2)); -------------------------------------------------------------------------------- /longestIncreasingSubarray.js: -------------------------------------------------------------------------------- 1 | /* 2 | Longest increasing subarray 3 | Given an array containing n numbers. The problem is to find the length of the longest contiguous 4 | subarray such that every element in the subarray is strictly greater than its previous element in the same 5 | subarray. Time Complexity should be O(n). 6 | 7 | Examples: 8 | 9 | Input : arr[] = {5, 6, 3, 5, 7, 8, 9, 1, 2} 10 | Output : 5 11 | The subarray is {3, 5, 7, 8, 9} 12 | 13 | Input : arr[] = {12, 13, 1, 5, 4, 7, 8, 10, 10, 11} 14 | Output : 4 15 | The subarray is {4, 7, 8, 10} 16 | 17 | */ 18 | 19 | /*Longest Increasing subarray, continuo*/ 20 | function longestIncreasingSubarray(nums){ 21 | var max = 0; 22 | var count = 1; 23 | if(nums.length === 0) return 0; 24 | for(let i = 0; i < nums.length; i++){ 25 | /*Si el siguiente elemento es mayor al actual 26 | incrementamos el contador y actualizamos nuestro 27 | resultado*/ 28 | if(nums[i+1] > nums[i]){ 29 | count++; 30 | max = Math.max(max, count); 31 | }else{ 32 | /*Reseteamos el contador*/ 33 | //Reset 34 | count = 1; 35 | } 36 | } 37 | return max; 38 | } 39 | 40 | nums = [12, 13, 1, 5, 4, 7, 8, 10, 10, 11]; 41 | console.log(longestIncreasingSubarray(nums)); -------------------------------------------------------------------------------- /longestPathInBinaryTree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, find its maximum depth. 3 | 4 | The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 5 | 6 | Note: A leaf is a node with no children. 7 | 8 | Example: 9 | 10 | Given binary tree [3,9,20,null,null,15,7], 11 | 12 | 3 13 | / \ 14 | 9 20 15 | / \ 16 | 15 7 17 | 18 | return its depth = 3. 19 | 20 | 21 | https://leetcode.com/problems/maximum-depth-of-binary-tree/ 22 | 23 | */ 24 | 25 | var maxDepth = function(root) { 26 | return heightTree(root); 27 | }; 28 | 29 | function heightTree(root){ 30 | if(root === null){ 31 | return 0; 32 | } 33 | let left = heightTree(root.left); 34 | let right = heightTree(root.right); 35 | return Math.max(left, right) + 1; 36 | } 37 | -------------------------------------------------------------------------------- /maxProductSubarray.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which 3 | has the largest product. 4 | 5 | Example 1: 6 | 7 | Input: [2,3,-2,4] 8 | Output: 6 9 | Explanation: [2,3] has the largest product 6. 10 | Example 2: 11 | 12 | Input: [-2,0,-1] 13 | Output: 0 14 | Explanation: The result cannot be 2, because [-2,-1] is not a subarray. 15 | 16 | https://leetcode.com/problems/maximum-product-subarray/description/ 17 | */ 18 | 19 | /* 20 | To find the max we have three choices: 21 | 1. If the current element is positive integer 22 | 2. If the current element is negative 23 | 3. If the current element is a starting point 24 | 25 | https://www.youtube.com/watch?v=vtJvbRlHqTA 26 | */ 27 | var maxProduct = function(nums) { 28 | 29 | if(nums.length == 0) return 0; 30 | 31 | let prevMaxProduct = nums[0]; 32 | let prevMinProduct = nums[0]; 33 | let currentMaxProd = nums[0]; 34 | let currentMidProd = nums[0]; 35 | let answer = nums[0]; 36 | 37 | for(let i = 1; i < nums.length; i++) { 38 | currentMaxProd = Math.max(prevMaxProduct * nums[i], prevMinProduct * nums[i], nums[i]); 39 | currentMidProd = Math.min(prevMaxProduct * nums[i], prevMinProduct * nums[i], nums[i]); 40 | answer = Math.max(currentMaxProd, answer); 41 | // Update 42 | prevMaxProduct = currentMaxProd 43 | prevMinProduct = currentMidProd 44 | } 45 | 46 | return answer; 47 | 48 | }; 49 | 50 | 51 | 52 | var maxProduct = function(nums) { 53 | 54 | if(nums.length == 0) return 0; 55 | 56 | let maxProduct = nums[0]; 57 | let minProduct = nums[0]; 58 | let maxRes = nums[0]; 59 | 60 | for(let i = 1; i < nums.length; i++) { 61 | if(nums[i] >= 0) { 62 | maxProduct = Math.max(maxProduct * nums[i], nums[i]); 63 | minProduct = Math.min(minProduct * nums[i], nums[i]); 64 | } else { 65 | let tmp = maxProduct; 66 | maxProduct = Math.max(minProduct * nums[i], nums[i]); 67 | minProduct = Math.min(tmp * nums[i], nums[i]); 68 | } 69 | 70 | maxRes = Math.max(maxRes, maxProduct); 71 | } 72 | 73 | return maxRes; 74 | 75 | }; -------------------------------------------------------------------------------- /maxSubArrayLen.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.programcreek.com/2014/10/leetcode-maximum-size-subarray-sum-equals-k-java/ 3 | */ 4 | 5 | function maxSubArrayLen(nums, k) { 6 | let map = {}; 7 | let max = 0; 8 | let sum = 0; 9 | 10 | for(let i=0; i < nums.length; i++) { 11 | sum += nums[i]; 12 | if(sum === k) { 13 | max = Math.max(max, i+1); 14 | } 15 | 16 | let diff = sum - k; 17 | if(diff in map) { 18 | max = Math.max(max, i - map[diff]); 19 | } 20 | 21 | if(!(sum in map)){ 22 | map[sum] = i; 23 | } 24 | } 25 | return max; 26 | } 27 | 28 | nums = [1, -1, 5, -2, 3]; 29 | k = 3; 30 | 31 | console.log(maxSubArrayLen(nums, k)); -------------------------------------------------------------------------------- /maximalSquare.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. 3 | 4 | Example: 5 | 6 | Input: 7 | 8 | 1 0 1 0 0 9 | 1 0 1 1 1 10 | 1 1 1 1 1 11 | 1 0 0 1 0 12 | 13 | Output: 4 14 | 15 | https://leetcode.com/problems/maximal-square/description/ 16 | https://www.youtube.com/watch?v=_Lf1looyJMU 17 | 18 | */ 19 | 20 | var maximalSquare = function(matrix) { 21 | 22 | if(matrix.length === 0) { 23 | return 0; 24 | } 25 | 26 | let dp = new Array(matrix.length); 27 | for(let i = 0; i < dp.length; i++) { 28 | dp[i] = new Array(matrix[0].length).fill(0); 29 | } 30 | 31 | let m = matrix.length; 32 | let n = matrix[0].length; 33 | let max = 0; 34 | 35 | // Pasamos los de los corners ya que no hay mas elementos 36 | for(let i = 0; i < m; i++) { 37 | dp[i][0] = matrix[i][0]; 38 | // Corner case [1] 39 | if(dp[i][0] === 1) { 40 | max = 1; 41 | } 42 | } 43 | 44 | for(let i = 0; i < n; i++) { 45 | dp[0][i] = matrix[0][i]; 46 | // Corner case [1] 47 | if(dp[0][i] === 1) { 48 | max = 1; 49 | } 50 | } 51 | 52 | for(let i = 1; i < m; i++) { 53 | for(let j = 1; j < n; j++) { 54 | if(matrix[i][j] === 1) { 55 | dp[i][j] = Math.min(dp[i][j-1], dp[i-1][j-1], dp[i-1][j]) + 1; 56 | max = Math.max(max, dp[i][j]); 57 | } 58 | } 59 | } 60 | 61 | return max * max; 62 | 63 | }; 64 | 65 | 66 | matrix = [ 67 | [1,1,0,1,0], 68 | [0,1,1,1,0], 69 | [1,1,1,1,0], 70 | [0,1,1,1,1], 71 | ]; 72 | 73 | console.log(maximalSquare(matrix)); -------------------------------------------------------------------------------- /meetingRooms.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of meeting time intervalsof start and end times [[s1,ed], [s2, e2]..] determine if a person coudld attend al meetings 3 | 4 | https://leetcode.com/problems/meeting-rooms/ 5 | https://www.youtube.com/watch?v=i2bBG7CaVxs 6 | https://github.com/JBayona/Facebook-Interview-Coding-1/blob/master/253.%20Meeting%20Rooms%20II.java 7 | */ 8 | 9 | // Greedy algorithm 10 | var canAttendMeetings = function(intervals) { 11 | // Sort the intervals per end time so we can check if collapses 12 | let sorted = intervals.sort((a,b) => a.end - b.end); 13 | 14 | for(let i = 1 ; i < intervals.length; i++) { 15 | if(sorted[i].start < sorted[i-1].end) { 16 | return false; 17 | } 18 | } 19 | 20 | return true; 21 | }; 22 | 23 | var canAttendMeetings = function(intervals) { 24 | // Sort the intervals per end time so we can check if collapses 25 | let sorted = intervals.sort((a,b) => a.start - b.start); 26 | 27 | for(let i = 1 ; i < intervals.length; i++) { 28 | if(sorted[i].start < sorted[i-1].end) { 29 | return false; 30 | } 31 | } 32 | 33 | return true; 34 | }; 35 | 36 | //intervals = [{start: 0, end: 30}, {start: 5, end: 10}, {start: 15, end: 20}]; // false 37 | intervals = [{start: 7, end: 10}, {start: 2, end: 4}]; // true 38 | console.log(canAttendMeetings(intervals)); 39 | 40 | // Opción 2 41 | var canAttendMeetings = function(intervals) { 42 | // Sort the intervals per end time so we can check if collapses 43 | let starts = []; 44 | let ends = []; 45 | 46 | for(let i = 0; i < intervals.length; i++) { 47 | starts[i] = intervals[i].start; 48 | ends[i] = intervals[i].end; 49 | } 50 | 51 | for(let i = 0 ; i < intervals.length - 1; i++) { 52 | if(start[i + 1] < ends[i]) { 53 | return false; 54 | } 55 | } 56 | 57 | return true; 58 | }; 59 | 60 | // Meeting rooms 2 61 | 62 | /* 63 | Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] find the minimum number of conference rooms required. 64 | https://www.youtube.com/watch?v=GmpyAMpjpUY 65 | */ 66 | 67 | // Opción 1 68 | // Greedy 69 | function minMeetingRooms(intervals) { 70 | if(invervals.length === 0 || !intervals) { 71 | return 0; 72 | } 73 | 74 | let starts = []; 75 | let ends = []; 76 | 77 | for(let i = 0; i < intervals.length; i++) { 78 | starts[i] = intervals[i].start; 79 | ends[i] = intervals[i].end; 80 | } 81 | 82 | starts.sort(); 83 | ends.sort(); 84 | 85 | let count = 0; 86 | let end = 0; 87 | for(let i = 0; i < intervals.length; i++) { 88 | if(start[i] < ends[end]) { 89 | count++; 90 | } else { 91 | end++; 92 | } 93 | } 94 | 95 | return count = 0; 96 | 97 | } 98 | 99 | //Opción 2 100 | /* 101 | Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] find the minimum number of conference rooms required. 102 | */ 103 | 104 | public int minMeetingRooms(Interval[] intervals) { 105 | if (intervals == null || intervals.length == 0) return 0; 106 | 107 | Arrays.sort(intervals, new Comparator(){ 108 | public int compare(Interval i1, Interval i2) { 109 | return i1.start - i2.start; 110 | } 111 | }); 112 | 113 | 114 | // Min heap 115 | // We sort by end so we can extend or reuse the meeting room, that´s why we use end time. 116 | PriorityQueue pq = new PriorityQueue<>(new Comparator(){ 117 | public int compare(Interval i1, Interval i2) { 118 | return i1.end - i2.end; 119 | } 120 | }); 121 | pq.add(intervals[0]); 122 | 123 | for (int i = 1; i < intervals.length; i++) { 124 | Interval interval = pq.poll(); 125 | // If the current event is greater thatn the earliest end time 126 | // Means we can reuse the room, so we "extend" the event and 127 | // later will be added again 128 | if (intervals[i].start >= interval.end) 129 | // Means we need another room 130 | interval.end = intervals[i].end; 131 | else 132 | // There´s a conflict and we need to add them to the minheap 133 | pq.add(intervals[i]); 134 | pq.add(interval); 135 | } 136 | 137 | // The number of rooms will be the size of the heap 138 | return pq.size(); 139 | } 140 | 141 | // Example = [[0, 30], [5, 10], [15, 20]]; 142 | // Result = 2 -------------------------------------------------------------------------------- /merge k sorted lists-arrays.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. 3 | 4 | Note: 5 | 6 | The number of elements initialized in nums1 and nums2 are m and nrespectively. 7 | You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. 8 | Example: 9 | 10 | Input: 11 | nums1 = [1,2,3,0,0,0], m = 3 12 | nums2 = [2,5,6], n = 3 13 | 14 | Output: [1,2,2,3,5,6] 15 | 16 | https://leetcode.com/problems/merge-sorted-array/ 17 | 18 | */ 19 | 20 | var merge = function(nums1, m, nums2, n) { 21 | /*Empezamos de atrás para el nuevo arreglo*/ 22 | while(m > 0 && n > 0) { 23 | if (nums1[m - 1] > nums2[n - 1]) { 24 | /*m + n - 1 porque tendra el tamaño de los 25 | dos arreglos*/ 26 | nums1[m + n - 1] = nums1[m - 1]; 27 | m--; 28 | } else { 29 | nums1[m + n - 1] = nums2[n - 1]; 30 | n--; 31 | } 32 | } 33 | 34 | /*En caso de que el segundo arreglo sea mayor*/ 35 | while (n > 0) { 36 | nums1[n - 1] = nums2[n - 1]; 37 | n--; 38 | } 39 | }; 40 | 41 | // Merge two sorted lists 42 | 43 | //classic iterate 44 | function mergeTwoLists(l1, l2) { 45 | let dummy = new ListNode(0);//dummy 46 | let p = dummy; 47 | while (l1 && l2) { 48 | if (l1.val < l2.val) { 49 | p.next = l1; 50 | l1 = l1.next; 51 | } else { 52 | p.next = l2; 53 | l2 = l2.next; 54 | } 55 | p = p.next; 56 | } 57 | if (l1) p.next = l1; 58 | if (l2) p.next = l2; 59 | return dummy.next; 60 | } 61 | 62 | //recursive 63 | function mergeTwoLists(l1, l2) { 64 | if (l1 == null) return l2; 65 | if (l2 == null) return l1; 66 | if (l1.val < l2.val) { 67 | l1.next = mergeTwoLists(l1.next, l2); 68 | return l1; 69 | } else { 70 | l2.next = mergeTwoLists(l2.next, l1); 71 | return l2; 72 | } 73 | } 74 | 75 | // Merge K LinkedLists 76 | // O(nk Log k) 77 | public class Solution { 78 | public ListNode mergeKLists(ListNode[] lists) { 79 | if (lists.length == 0) return null; 80 | // Minheadp (El nodo es menor o igual al de sus hijos) 81 | PriorityQueue queue = new PriorityQueue<>(lists.length, (x, y) -> x.val - y.val); 82 | // push the head nodes of all the k lists in 'pq' 83 | for (ListNode node : lists) { 84 | if (node != null) { 85 | queue.add(node); 86 | } 87 | } 88 | 89 | // Nodo temporal 90 | ListNode head = new ListNode(0); 91 | ListNode p = head; 92 | // Mientras tengamos elementos en la pq 93 | while (!queue.isEmpty()) { 94 | // Saca el menor 95 | ListNode node = queue.poll(); 96 | p.next = node; 97 | // Recorremos 98 | p = p.next; 99 | // Agregamos el next de nuestro nodo actual a la pq 100 | if (node.next != null) { 101 | queue.add(node.next); 102 | } 103 | } 104 | return head.next; 105 | } 106 | } -------------------------------------------------------------------------------- /mergeTwoIntervals.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given A and B two interval lists, A has no overlap inside A and B has no overlap inside B. Write the function to merge two interval lists, output the result with no overlap. Ask for a very efficient solution 3 | 4 | A naive method can combine the two list, and sort and apply merge interval in the leetcode, but is not efficient enough. 5 | 6 | For example, 7 | A: [1,5], [10,14], [16,18] 8 | B: [2,6], [8,10], [11,20] 9 | 10 | output [1,6], [8, 20] 11 | 12 | */ 13 | 14 | // Time complexity O(m + n) 15 | // Space complexity O(m + n ) 16 | function mergeInterval(intervalA, intervalB) { 17 | let res = []; 18 | let lastInterval = []; 19 | let current = []; 20 | 21 | let indexA = 0; 22 | let indexB = 0; 23 | 24 | // Two pointers 25 | while(indexA < intervalA.length && indexB < intervalB.length) { 26 | let elementsA = intervalA[indexA]; 27 | let elementsB = intervalB[indexB]; 28 | 29 | // Current always has the less element 30 | if(elementsA[0] < elementsB[0]) { 31 | current = elementsA; 32 | indexA++ 33 | } else { 34 | current = elementsB; 35 | indexB++ 36 | } 37 | 38 | lastInterval = mergeIntervals(res, lastInterval, current); 39 | } 40 | 41 | // We still need to iterate for the remaining elements on interval A 42 | while (indexA < intervalA.length) { 43 | lastInterval = mergeIntervals(res, lastInterval, intervalA[indexA]); 44 | indexA++; 45 | } 46 | 47 | // We still need to iterate for the remaining elements on interval B 48 | while (indexB < intervalB.length) { 49 | lastInterval = mergeIntervals(res, lastInterval, intervalB[indexB]); 50 | indexB++; 51 | } 52 | 53 | if (lastInterval !== null) { 54 | res.push(lastInterval); 55 | } 56 | return res; 57 | } 58 | 59 | function mergeIntervals(res, lastInterval, current) { 60 | // The very first merge 61 | if(!lastInterval.length) { 62 | return current; 63 | } 64 | 65 | // current.start > lastInterval.end 66 | if(current[0] > lastInterval[1]) { 67 | res.push(lastInterval); 68 | return current 69 | } 70 | 71 | lastInterval[1] = Math.max(lastInterval[1], current[1]); 72 | return lastInterval; 73 | } 74 | 75 | // intervalA = [[1,5], [10,14], [16,18]]; 76 | // intervalB = [[2,6], [8,10], [11,20]]; 77 | // [1,6], [8, 20] 78 | 79 | // intervalA = []; 80 | // intervalB = [[2,6], [8,10], [11,20]]; 81 | // [2,6], [8,10], [11,20] 82 | 83 | intervalA = [[1,2], [3, 4], [6, 7], [15, 18], [21, 22]]; 84 | intervalB = [[2,6], [8,10], [11,20]]; 85 | // [[1, 7], [8,10], [11, 20], [21, 22]] 86 | console.log(mergeInterval(intervalA, intervalB)); -------------------------------------------------------------------------------- /minSizeSubarraySum.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous 3 | subarray of which the sum ≥ s. If there isn't one, return 0 instead. 4 | 5 | Example: 6 | 7 | Input: s = 7, nums = [2,3,1,2,4,3] 8 | Output: 2 9 | Explanation: the subarray [4,3] has the minimal length under the problem constraint. 10 | Follow up: 11 | If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n). 12 | 13 | 14 | https://leetcode.com/problems/minimum-size-subarray-sum/ 15 | */ 16 | 17 | var minSubArrayLen = function(s, nums) { 18 | if(!nums || !nums.length) { 19 | return 0; 20 | } 21 | let sum = 0; 22 | let i = 0; 23 | let j = 0; 24 | let min = Number.MAX_SAFE_INTEGER; 25 | 26 | 27 | while(j < nums.length) { 28 | sum += nums[j++]; 29 | while(sum >= s) { 30 | min = Math.min(min, j - i); 31 | sum -= nums[i++]; 32 | } 33 | } 34 | 35 | return min === Number.MAX_SAFE_INTEGER ? 0 : min; 36 | }; -------------------------------------------------------------------------------- /minStepToReachTargetKnight.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | BFS 4 | 5 | https://www.geeksforgeeks.org/minimum-steps-reach-target-knight/ 6 | 7 | Given a square chessboard of N x N size, the position of Knight and position of a target is given. 8 | We need to find out minimum steps a Knight will take to reach the target position. 9 | 10 | */ 11 | function minStepToReachTarget(N, knightPost, targetPost) { 12 | let visited = new Array(N + 1); 13 | for(let i = 0; i < N + 1; i++) { 14 | visited[i] = new Array(N + 1).fill(false); 15 | } 16 | 17 | // Control the status of the queue 18 | let queue = []; 19 | 20 | // Places where the knight in chess (guerrero) can move 21 | let row = [2, 2, -2, -2, 1, 1, -1, -1]; 22 | let col = [1, -1, 1, -1, 2, -2, 2, -2]; 23 | // Add first element in the queue 24 | queue.push(new Node(knightPost[0], knightPost[1], 0)); 25 | // Mark as visited the first element 26 | visited[knightPost[0]][knightPost[1]] = true; 27 | 28 | // Loop until we have one element in the queue 29 | while(queue.length) { 30 | let node = queue.shift(); 31 | 32 | // If the location is the same, return the 33 | // distance, this is our goal 34 | if(node.x === targetPost[0] && node.y === targetPost[1]) { 35 | return node.distance; 36 | } 37 | 38 | // Return on all the possible states 39 | for(let i = 0; i < 8; i++) { 40 | let rowK = node.x + row[i]; 41 | let colK = node.y + col[i]; 42 | 43 | // If the cell has not been visited and the move is 44 | // inside the board 45 | if(isInside(rowK, colK, N) && !visited[rowK][colK]) { 46 | visited[rowK][colK] = true; 47 | queue.push(new Node(rowK, colK, node.distance + 1)); 48 | } 49 | } 50 | } 51 | 52 | return -1; 53 | } 54 | 55 | function Node(x, y, distance) { 56 | this.x = x; 57 | this.y = y; 58 | this.distance = distance; 59 | } 60 | 61 | // Checks whether given position is 62 | // inside the board 63 | function isInside(x, y, N) { 64 | if (x >= 1 && x <= N && y >= 1 && y <= N) { 65 | return true; 66 | } 67 | return false; 68 | } 69 | 70 | function isSafe(row, col, N, visited) { 71 | return ( 72 | (row >= 0 && row < N) && 73 | (col >= 0 && col < N) && 74 | (visited[row][col] === false) 75 | ); 76 | } 77 | 78 | 79 | N = 30; 80 | knightPost = [1, 1]; 81 | targetPost = [30, 30]; 82 | console.log(minStepToReachTarget(N, knightPost, targetPost)); -------------------------------------------------------------------------------- /minesweeper.js: -------------------------------------------------------------------------------- 1 | /* 2 | Let's play the minesweeper game (Wikipedia, online game)! 3 | 4 | You are given a 2D char matrix representing the game board. 'M' represents an unrevealed mine, 'E' represents an unrevealed empty square, 'B' represents a revealed blank square that has no adjacent (above, below, left, right, and all 4 diagonals) mines, digit ('1' to '8') represents how many mines are adjacent to this revealed square, and finally 'X' represents a revealed mine. 5 | 6 | Now given the next click position (row and column indices) among all the unrevealedsquares ('M' or 'E'), return the board after revealing this position according to the following rules: 7 | 8 | If a mine ('M') is revealed, then the game is over - change it to 'X'. 9 | If an empty square ('E') with no adjacent mines is revealed, then change it to revealed blank ('B') and all of its adjacent unrevealed squares should be revealed recursively. 10 | If an empty square ('E') with at least one adjacent mine is revealed, then change it to a digit ('1' to '8') representing the number of adjacent mines. 11 | Return the board when no more squares will be revealed. 12 | 13 | 14 | Example 1: 15 | 16 | Input: 17 | 18 | [['E', 'E', 'E', 'E', 'E'], 19 | ['E', 'E', 'M', 'E', 'E'], 20 | ['E', 'E', 'E', 'E', 'E'], 21 | ['E', 'E', 'E', 'E', 'E']] 22 | 23 | Click : [3,0] 24 | 25 | Output: 26 | 27 | [['B', '1', 'E', '1', 'B'], 28 | ['B', '1', 'M', '1', 'B'], 29 | ['B', '1', '1', '1', 'B'], 30 | ['B', 'B', 'B', 'B', 'B']] 31 | 32 | Explanation: 33 | 34 | Example 2: 35 | 36 | Input: 37 | 38 | [['B', '1', 'E', '1', 'B'], 39 | ['B', '1', 'M', '1', 'B'], 40 | ['B', '1', '1', '1', 'B'], 41 | ['B', 'B', 'B', 'B', 'B']] 42 | 43 | Click : [1,2] 44 | 45 | Output: 46 | 47 | [['B', '1', 'E', '1', 'B'], 48 | ['B', '1', 'X', '1', 'B'], 49 | ['B', '1', '1', '1', 'B'], 50 | ['B', 'B', 'B', 'B', 'B']] 51 | 52 | 53 | https://leetcode.com/problems/minesweeper/ 54 | 55 | */ 56 | 57 | // Option 1 58 | 59 | var updateBoard = function(board, click) { 60 | let x = click[0]; 61 | let y = click[1]; 62 | 63 | // If we hit the mine, just changed to 'X' and return the result 64 | if(board[x][y] === 'M') { 65 | board[x][y] = 'X'; 66 | return board; 67 | } 68 | 69 | dfs(x, y, board); 70 | return board; 71 | }; 72 | 73 | function dfs(x, y, board) { 74 | // Check if is a valid movement 75 | if(isSafe(x, y, board)) { 76 | let num = getNumsOfBombs(x, y, board); 77 | 78 | if (num == 0) { 79 | board[x][y] = 'B'; 80 | // Left, right, up, down and all diagonals 81 | let ROW = [-1, 0, 1, -1, 1, 0, 1, -1]; 82 | let COL = [-1, 1, 1, 0, -1, -1, 0, 1]; 83 | 84 | for (let i = 0; i < 8; i++) { 85 | let nextRow = x + ROW[i]; 86 | let nextCol = y + COL[i]; 87 | dfs(nextRow, nextCol, board); 88 | } 89 | } else { 90 | board[x][y] = num + ''; 91 | } 92 | } 93 | } 94 | 95 | function isSafe(x, y, board) { 96 | return ( 97 | (x >= 0 && x < board.length) && 98 | (y >= 0 && y < board[0].length) && 99 | (board[x][y] === 'E') 100 | ); 101 | } 102 | 103 | function getNumsOfBombs(x, y, board) { 104 | let num = 0; 105 | for (let i = -1; i <= 1; i++) { 106 | for (let j = -1; j <= 1; j++) { 107 | let row = x + i; 108 | let col = y + j; 109 | if (row < 0 || row >= board.length || col < 0 || col >= board[0].length) continue; 110 | if (board[row][col] == 'M' || board[row][col] == 'X') { 111 | num++; 112 | } 113 | } 114 | } 115 | return num; 116 | } 117 | 118 | // Option 2 119 | 120 | /** 121 | * @param {character[][]} board 122 | * @param {number[]} click 123 | * @return {character[][]} 124 | */ 125 | var updateBoard = function(board, click) { 126 | let x = click[0]; 127 | let y = click[1]; 128 | 129 | // If we hit the mine, just changed to 'X' and return the result 130 | if(board[x][y] === 'M') { 131 | board[x][y] = 'X'; 132 | return board; 133 | } 134 | 135 | dfs(x, y, board); 136 | return board; 137 | }; 138 | 139 | function dfs(x, y, board) { 140 | 141 | // Left, right, up, down and all diagonals 142 | let ROW = [-1, 0, 1, -1, 1, 0, 1, -1]; 143 | let COL = [-1, 1, 1, 0, -1, -1, 0, 1]; 144 | for(let i = 0; i < 8; i++) { 145 | let nextRow = ROW[i] + x; 146 | let nextCol = COL[i] + y; 147 | 148 | if(isSafe(nextRow, nextCol, board)) { 149 | let num = getNumsOfBombs(x, y, board); 150 | if(num === 0) { 151 | board[x][y] = 'B'; 152 | dfs(nextRow, nextCol, board); 153 | } else { 154 | board[x][y] = num + ''; 155 | } 156 | } 157 | } 158 | } 159 | 160 | function isSafe(x, y, board) { 161 | return ( 162 | (x >= 0 && x < board.length) && 163 | (y >= 0 && y < board[0].length) && 164 | (board[x][y] === 'E') 165 | ); 166 | } 167 | 168 | function getNumsOfBombs(x, y, board) { 169 | let num = 0; 170 | for (let i = -1; i <= 1; i++) { 171 | for (let j = -1; j <= 1; j++) { 172 | let row = x + i; 173 | let col = y + j; 174 | if (row < 0 || row >= board.length || col < 0 || col >= board[0].length) continue; 175 | if (board[row][col] == 'M' || board[row][col] == 'X') { 176 | num++; 177 | } 178 | } 179 | } 180 | return num; 181 | } -------------------------------------------------------------------------------- /minimumRemovalPalindrome.js: -------------------------------------------------------------------------------- 1 | // Dynamic Programming 2 | // Reference: https://www.youtube.com/watch?v=NnD96abizww 3 | // https://github.com/mission-peace/interview/blob/master/src/com/interview/dynamic/LongestCommonSubsequence.java 4 | var minimumRemovalPalindrome = function(str) { 5 | if(!str || !str.length) { 6 | return 0; 7 | } 8 | 9 | let n = str.length; 10 | let reverse = str.split('').reverse().join(''); 11 | 12 | let lcs = longestCommonSubsequence(str, reverse); 13 | 14 | return n - lcs; 15 | } 16 | 17 | var longestCommonSubsequence = function(str1, str2) { 18 | let dp = new Array(str1.length + 1); 19 | let max = 0; 20 | 21 | // Create our dp table 22 | for(let i = 0; i < dp.length; i++) { 23 | dp[i] = new Array(str2.length + 1).fill(0); 24 | } 25 | 26 | for(let i = 1; i < dp.length; i++) { 27 | for(let j = 1; j < dp[i].length; j++) { 28 | if(str1[i-1] === str2[j-1]) { 29 | dp[i][j] = dp[i-1][j-1] + 1; 30 | } else { 31 | dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); 32 | } 33 | if(dp[i][j] > max) { 34 | max = dp[i][j]; 35 | } 36 | } 37 | } 38 | console.log(dp); 39 | return max; 40 | } 41 | 42 | str = "abcdaf"; 43 | console.log(minimumRemovalPalindrome(str)); -------------------------------------------------------------------------------- /mostFrequentCharacterInString.js: -------------------------------------------------------------------------------- 1 | function findMostFrequent(str) { 2 | let hash = {}; 3 | let max = 0; 4 | let letter; 5 | 6 | for(let i = 0; i < str.length; i++) { 7 | if(str[i] in hash) { 8 | hash[str[i]]++; 9 | } else { 10 | hash[str[i]] = 1; 11 | } 12 | 13 | if(hash[str[i]] > max) { 14 | max = hash[str[i]]; 15 | letter = str[i]; 16 | } 17 | } 18 | 19 | console.log(hash); 20 | console.log(letter); 21 | return max; 22 | } 23 | 24 | str = 'testingfrequency'; 25 | console.log(findMostFrequent(str)); -------------------------------------------------------------------------------- /mostFrequentSubtreeSum.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to 3 | the original key plus sum of all keys greater than the original key in BST. 4 | 5 | Example: 6 | 7 | Input: The root of a Binary Search Tree like this: 8 | 5 9 | / \ 10 | 2 13 11 | 12 | Output: The root of a Greater Tree like this: 13 | 18 14 | / \ 15 | 20 13 16 | 17 | 18 | https://leetcode.com/problems/most-frequent-subtree-sum/submissions/ 19 | 20 | */ 21 | 22 | var findFrequentTreeSum = function(root) { 23 | let result = []; 24 | let hash = {}; 25 | let freq = [0]; 26 | // Get the sum of the subtree 27 | getSumSubtrees(root, hash, freq); 28 | 29 | // Here we'll get only those sums with the same frequency as "freq" 30 | for(let sum in hash) { 31 | if(hash[sum] === freq[0]) { 32 | result.push(sum); 33 | } 34 | } 35 | return result; 36 | }; 37 | 38 | 39 | 40 | function getSumSubtrees(node, hash, freq){ 41 | // Base case 42 | if(!node){ 43 | return 0; 44 | } 45 | 46 | let left = getSumSubtrees(node.left, hash, freq); 47 | let right = getSumSubtrees(node.right, hash, freq); 48 | let sum = left + right + node.val; 49 | 50 | if(sum in hash) { 51 | hash[sum]++; 52 | } else { 53 | hash[sum] = 1; 54 | } 55 | 56 | // Get the max frequency of the current sum of the previous registered 57 | // This will help us to only track from our elements those with the same 58 | // frequency registered. 59 | freq[0] = Math.max(freq[0], hash[sum]); 60 | return sum; 61 | } 62 | -------------------------------------------------------------------------------- /moveZeros.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. 3 | 4 | For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0]. 5 | 6 | Note: 7 | You must do this in-place without making a copy of the array. 8 | Minimize the total number of operations. 9 | 10 | https://leetcode.com/problems/move-zeroes/description/ 11 | */ 12 | 13 | //Ceros atras orden 14 | var moveZeroes = function(nums) { 15 | var index = 0; 16 | var tmp = 0; 17 | for(let i = 0; i < nums.length; i++){ 18 | //Si hay un numero diferente de cero 19 | if(nums[i]){ 20 | //Almacenamos ese numero temporal en una variable 21 | tmp = nums[i]; 22 | /*Ponemos en ese valor lo que este en nuestra posicion 23 | controlada por index */ 24 | nums[i] = nums[index]; 25 | /*index controla los valores que vamos poniendo de atras 26 | para adelante*/ 27 | nums[index] = tmp; 28 | /*Incrementamos index*/ 29 | index++; 30 | } 31 | } 32 | return nums; 33 | }; 34 | 35 | nums = [0, 1, 0, 3, 12] 36 | console.log(moveZeroes(nums)); 37 | 38 | 39 | //Ceros Adelante 40 | var moveZeroes = function(nums) { 41 | var index = 0; 42 | for(let i = 0; i < nums.length; i++){ 43 | if(nums[i] === 0){ 44 | nums[i] = nums[index]; 45 | nums[index++] = 0; 46 | } 47 | } 48 | return nums; 49 | }; 50 | 51 | //Ceros Atras sin orden 52 | var moveZeroes = function(nums) { 53 | var index = nums.length-1; 54 | for(let i = 0; i < nums.length; i++){ 55 | if(nums[i] === 0 && i < index){ 56 | nums[i] = nums[index]; 57 | nums[index--] = 0; 58 | } 59 | } 60 | return nums; 61 | }; 62 | 63 | nums = [0, 1, 0, 3, 12] 64 | console.log(moveZeroes(nums)); -------------------------------------------------------------------------------- /numIslands.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by 3 | water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the 4 | grid are all surrounded by water. 5 | 6 | Example 1: 7 | 8 | Input: 9 | 11110 10 | 11010 11 | 11000 12 | 00000 13 | 14 | Output: 1 15 | Example 2: 16 | 17 | Input: 18 | 11000 19 | 11000 20 | 00100 21 | 00011 22 | 23 | Output: 3 24 | 25 | https://leetcode.com/problems/number-of-islands/description/ 26 | */ 27 | 28 | /** 29 | * @param {character[][]} grid 30 | * @return {number} 31 | */ 32 | var numIslands = function(grid) { 33 | let visited = new Array(grid.length); 34 | let count = 0; 35 | for(let i = 0; i < visited.length; i++) { 36 | visited[i] = new Array(grid[i].length).fill(false); 37 | } 38 | 39 | for(let i = 0; i < grid.length; i++) { 40 | for(let j = 0; j < grid[i].length; j++) { 41 | if(grid[i][j] === '1' && !visited[i][j]) { 42 | visited[i][j] = true; 43 | dfs(grid, visited, i, j); 44 | count++; 45 | } 46 | } 47 | } 48 | return count; 49 | }; 50 | 51 | function dfs(grid, visited, x, y) { 52 | let nextX = [-1, 0, 0, 1]; 53 | let nextY = [-0, -1, 1, 0]; 54 | 55 | for(let i = 0; i < 4; i++) { 56 | let moveX = x + nextX[i]; 57 | let moveY = y + nextY[i]; 58 | if(isSafe(grid, visited, moveX, moveY)) { 59 | visited[moveX][moveY] = true; 60 | dfs(grid, visited, moveX, moveY); 61 | } 62 | } 63 | } 64 | 65 | function isSafe(grid, visited, x, y) { 66 | return( 67 | x >= 0 && x < grid.length && 68 | y >= 0 && y < grid[0].length && 69 | grid[x][y] === '1' && 70 | !visited[x][y] 71 | ); 72 | } -------------------------------------------------------------------------------- /numberToWords.js: -------------------------------------------------------------------------------- 1 | /* 2 | Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1. 3 | 4 | Example 1: 5 | 6 | Input: 123 7 | Output: "One Hundred Twenty Three" 8 | Example 2: 9 | 10 | Input: 12345 11 | Output: "Twelve Thousand Three Hundred Forty Five" 12 | Example 3: 13 | 14 | Input: 1234567 15 | Output: "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven" 16 | Example 4: 17 | 18 | Input: 1234567891 19 | Output: "One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety 20 | 21 | https://leetcode.com/problems/integer-to-english-words/description/ 22 | 23 | 24 | Vamos dividiendo de 3 en 3, por ejemplo: 25 | 123 = 123 26 | 1234 = Primero analizamos 234 y después sólo el 1 27 | 12345 = 345 y 12 28 | 123456 = 456 y 123 29 | 1234567 = 567, 234 y 1 = One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven 30 | */ 31 | 32 | let lessThan20 = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 33 | 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen']; 34 | let tens = ['', 'Ten', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety']; 35 | let thousands = ['', 'Thousand', 'Million', 'Billion']; 36 | 37 | var numberToWords = function(num) { 38 | 39 | // Corner case 40 | if(num === 0) return 'Zero'; 41 | 42 | let result = ''; 43 | let i = 0; 44 | // Keep looping while we get zero 45 | while(num > 0) { 46 | if(num % 1000 !== 0) { 47 | result = helper(num % 1000) + thousands[i] + ' ' + result; 48 | } 49 | num = Math.floor(num/1000); 50 | i++; 51 | } 52 | 53 | return result.trim(); // Remove trailing spaces 54 | }; 55 | 56 | function helper(num) { 57 | if(num === 0) return ''; // necessary! 50868 58 | else if(num < 20) return lessThan20[num] + ' '; // 1 - 19 59 | else if(num < 100) return tens[Math.floor(num / 10)] + ' ' + helper(num % 10); // 20, 30, 40, 50, 60, 70, 80, 90 60 | else return lessThan20[Math.floor(num / 100)] + ' Hundred ' + helper(num % 100); // > 100 61 | } 62 | 63 | // n = 1234567; 64 | // n = 1000010; 65 | n = 1000; 66 | // n = 0; 67 | console.log(numberToWords(n)); -------------------------------------------------------------------------------- /oneEditDistance.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given two strings S and T, determine if they are both one edit distance apart. 3 | */ 4 | 5 | //O(N) 6 | 7 | function onEditDistance(s1,s2) { 8 | let len1 = s1.length; 9 | let len2 = s2.length; 10 | 11 | let len = Math.min(len1,len2); 12 | 13 | for(let i = 0; i < len; i++) { 14 | // Check only those who are different 15 | if(s1[i] !== s2[i]) { 16 | // Replace case, delete the diff char in both string 17 | if(len1 === len2) { 18 | return s1.substring(i+1) === s2.substring(i+1); 19 | } else if(len1 < len2) { // Delete one char from s2 20 | return s1.substring(i) === s2.substring(i+1); 21 | } else { // Delete one char from s1 22 | return s1.substring(i+1) === s2.substring(i); 23 | } 24 | } 25 | } 26 | 27 | return Math.abs(len1 - len2) === 1; // Corner case: "" 28 | 29 | } 30 | 31 | s1 = "ab"; 32 | s2 = "aa"; 33 | 34 | console.log(onEditDistance(s1,s2)); 35 | 36 | // Opt2 37 | // O(N) 38 | 39 | function onEditDistance(s1,s2) { 40 | let len1 = s1.length; 41 | let len2 = s2.length; 42 | 43 | // If the difference between both is greater than 1 44 | // it's not possible to get the string 45 | if(Math.abs(len1 - len2) > 1) { 46 | return false; 47 | } 48 | 49 | let i = 0; 50 | let j = 0; 51 | let count = 0; 52 | 53 | while(i < len1 && j < len2) { 54 | if(s1[i] === s2[j]) { 55 | i++; 56 | j++; 57 | } else { // If the're different 58 | count++; 59 | if(count > 1) { 60 | return false; 61 | } 62 | if(len1 > len2) { // increase variable that controls s1 (delete char from s1) 63 | i++; 64 | } else if(len1 < len2) { // increase variable that conttrols s2 (delete char from s2) 65 | j++; 66 | } else { // both has the same length, so we just need to advance (replace) 67 | i++; 68 | j++; 69 | } 70 | } 71 | } 72 | 73 | // If we have not analyzed part of some our of strings 74 | if(i < len1 || j < len2) { 75 | count++; 76 | } 77 | 78 | return count <= 1; 79 | 80 | } 81 | 82 | s1 = "ad"; 83 | s2 = "a"; 84 | 85 | console.log(onEditDistance(s1,s2)); 86 | -------------------------------------------------------------------------------- /powerMode.js: -------------------------------------------------------------------------------- 1 | /* 2 | Power Mod 3 | 4 | Calculates a to the power of b, mod c. 5 | (x*y)%z == ((x%z)*y)%z == (x*(y%z))%z 6 | Examples: 7 | PowMod(2,3,5) = 2*2*2 % 5 = 8%5 =3 8 | PowMod(3, 6, 7) = 3*3*3*3*3*3 % 7 = 729%7 =1. 9 | PowMod(16,16,5) = 1 10 | 11 | Solution: recursion 12 | Time: O(logb) 13 | 14 | */ 15 | 16 | function powmod(a, b , c){ 17 | return pow(a, b) % c; 18 | } 19 | // double a 20 | function pow(a, b) { 21 | if (b == 0) return 1; 22 | if (b % 2 == 0) return pow(a * a, b / 2); 23 | else return a * pow(a * a, b / 2); 24 | } 25 | 26 | 27 | // Pow(x, n) 28 | 29 | // Solution 1: nested pow 30 | function myPow(x, n) { 31 | if (n < 0) return (1 / x) * myPow(1 / x, -(n + 1)); // not myPow(1 / x, -n) -> will overflow when Integer.MIN_VALUE 32 | if (n == 0) return 1; 33 | if (n == 2) return x * x; 34 | if (n % 2 == 0) return myPow(myPow(x, n / 2), 2); 35 | else return x * myPow(myPow(x, n / 2), 2); 36 | } 37 | 38 | 39 | // Solution 2: double x 40 | function myPow(x, n) { 41 | if (n == 0 || x == 1) return 1; // necessary 42 | if (x == -1) return n % 2 == 0 ? 1 : -1; // necessary 43 | if (n == Number.MIN_SAFE_INTEGER) return 0; 44 | if (n < 0) { 45 | n = -n; 46 | x = 1 / x; 47 | } 48 | return n % 2 == 0 ? myPow(x * x, n / 2) : x * myPow(x * x, n / 2); 49 | } 50 | 51 | 52 | // Solution 3: double pow, recursive 53 | function myPow(x, n) { 54 | if (n == 0) return 1; 55 | let tmp = myPow(x, n / 2); 56 | if (n % 2 == 0) return tmp * tmp; 57 | else return n < 0 ? 1 / x * tmp * tmp : x * tmp * tmp; 58 | } 59 | 60 | 61 | // Solution 4: double pow, iterative 62 | function myPow(x, n) { 63 | if (n == 0 || x == 1) return 1; 64 | if (x == -1) return n % 2 == 0 ? 1 : -1; 65 | if (n == Number.MIN_SAFE_INTEGER) return 0; 66 | if (n < 0) { 67 | n = -n; 68 | x = 1 / x; 69 | } 70 | let res = 1; 71 | while (n > 0) { 72 | if ((n & 1) == 1) res *= x; // execude only when odd: n, 1; even: 1 73 | x *= x; // x to the power of 2 74 | n >>= 1; // divide the power by 2 75 | } 76 | return res; 77 | } -------------------------------------------------------------------------------- /previousAndNextPermutation.js: -------------------------------------------------------------------------------- 1 | /* 2 | Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. 3 | If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). 4 | The replacement must be in-place, do not allocate extra memory. 5 | Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. 6 | 1,2,3 → 1,3,2 7 | 3,2,1 → 1,2,3 8 | 1,1,5 → 1,5,1 9 | https://leetcode.com/problems/next-permutation/description/ 10 | */ 11 | 12 | var nextPermutation = function(nums){ 13 | var i = nums.length - 2; 14 | /*Checamos de atras hacia adelante, cada numero en 15 | nums[i+1] debe ser menor o igual a i, si esto se 16 | cumple decrementamos el i*/ 17 | while(i >= 0 && nums[i + 1] <= nums[i]){ 18 | i--; 19 | } 20 | if(i >= 0){ 21 | //Empieza a verificar desde atras del arreglo 22 | var j = nums.length - 1; 23 | /*Checando desde atras buscamos el primer elemento 24 | que sea mayor a nuestro elemento que quedamos con el 25 | index i, cuando lo encontramos no decrementamos j y 26 | hacemos swao de nums[i] con nums[j]*/ 27 | while(j >=0 && nums[j] <= nums[i]){ 28 | j--; 29 | } 30 | /*Hacemos el swap cuando encontramos el primer numero 31 | mayor de atras hacia adelante con el num[i]*/ 32 | //Swap 33 | [nums[i],nums[j]] = [nums[j],nums[i]]; 34 | } 35 | 36 | /*Ya que encontramos el primer elemento mas grande atras para adelante 37 | y hacemos swap, hacemos un reverse del array de i + 1 que fue el elemento 38 | que hicimos swap al final*/ 39 | console.log(reverseArray(nums, i + 1)); 40 | } 41 | 42 | function reverseArray(arr, start){ 43 | var i = start; 44 | var j = arr.length - 1; 45 | while(i < j){ 46 | //Swap 47 | [arr[i], arr[j]] = [arr[j], arr[i]]; 48 | i++; 49 | j--; 50 | } 51 | return arr; 52 | } 53 | 54 | var array = [1,5,8,4,7,6,5,3,1]; 55 | console.log(nextPermutation(array)); 56 | 57 | // https://www.geeksforgeeks.org/lexicographically-previous-permutation-in-c/ 58 | function prevPermutation(str) { 59 | 60 | // Last index of the string 61 | let n = str.length - 1; 62 | 63 | // Find the largest index i such 64 | // that str[i – 1] > str[i] 65 | let i = n; 66 | while(i > 0 && str[i-1] <= str[i]) { 67 | i--; 68 | } 69 | 70 | // if string is sorted in ascending order 71 | // we're at the last permutation 72 | if (i <= 0) { 73 | return false; 74 | } 75 | 76 | // Find largest index j such that j >= i and str[j] < str[i – 1] 77 | let j = i - 1; 78 | while(j + 1 <= n && str[j + 1] <= str[i - 1]) { 79 | j++; 80 | } 81 | 82 | // Swap character at i-1 with j 83 | strTmp = str.split(''); 84 | let tmp = strTmp[i-1]; 85 | strTmp[i-1] = strTmp[j]; 86 | strTmp[j] = tmp; 87 | 88 | // Need reverse? 89 | return strTmp.join(''); 90 | 91 | } 92 | 93 | str = "4321"; // 4312 94 | str = "4312"; // 4213 95 | console.log(prevPermutation(str)); -------------------------------------------------------------------------------- /printAllPathsIn2DBoard.js: -------------------------------------------------------------------------------- 1 | function printAllPath(board){ 2 | let res = []; 3 | let s = ''; 4 | dfs(board, res, s, 0, 0); 5 | return res; 6 | } 7 | 8 | function dfs(board, res, sb, x, y){ 9 | let len = sb.length; 10 | sb += board[y][x]; 11 | 12 | if( x == board[0].length - 1 && y == board.length - 1){ 13 | let s = sb.toString(); 14 | res.push(s); 15 | } else { 16 | if( x + 1 < board[0].length) dfs(board, res, sb, x+1, y); 17 | if( y + 1 < board.length ) dfs(board, res, sb, x, y+1); 18 | } 19 | sb = sb.slice(0, len); 20 | } 21 | 22 | 23 | grid = [ 24 | [1, 2, 3], 25 | [4, 5, 6], 26 | [7, 8, 9] 27 | ]; 28 | console.log(printAllPath(grid)); -------------------------------------------------------------------------------- /printTreeVerticalOp1.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.geeksforgeeks.org/print-binary-tree-vertical-order/ 3 | O(n^2) 4 | */ 5 | 6 | // Node 7 | function Node(val, left, right) { 8 | this.val = val; 9 | this.left = left || null; 10 | this.right = right || null; 11 | } 12 | 13 | function Values() { 14 | this.min = 0; 15 | this.max = 0 16 | } 17 | 18 | /* Find the min and max distance between the root 19 | node and the level, the root node is level 0, the 20 | first left child will be -1, next left will be -2 21 | and so on, for right child will be 1, then 2 and so 22 | on */ 23 | // A utility function to find min and max distances with respect to root 24 | function findMinMaxDistance(node, values, hd) { 25 | 26 | // Base case 27 | if(!node) { 28 | return; 29 | } 30 | 31 | //Update min and max 32 | if (hd < values.min) { 33 | values.min = hd; 34 | } else if (hd > values.max) { 35 | values.max = hd; 36 | } 37 | 38 | //Visit the left and right subtrees 39 | findMinMaxDistance(node.left, values, hd - 1); 40 | findMinMaxDistance(node.right, values, hd + 1); 41 | } 42 | 43 | 44 | // A utility function to print all nodes on a given line_no 45 | // hd is horizontal distance of current node with respect to root 46 | function printVerticalLine(tree, line, hd) { 47 | 48 | //Base case 49 | if(!tree) { 50 | return; 51 | } 52 | 53 | // The current line is the same of our tree 54 | if(line === hd) { 55 | console.log(tree.val); 56 | } 57 | 58 | printVerticalLine(tree.left, line, hd - 1); 59 | printVerticalLine(tree.right, line, hd + 1); 60 | } 61 | 62 | 63 | 64 | function printVertical(tree) { 65 | let values = new Values(); 66 | // Find the min and max levels of the tree following the root 67 | findMinMaxDistance(tree, values, 0) 68 | 69 | for(let i = values.min; i <= values.max; i++) { 70 | printVerticalLine(tree, i, 0) 71 | console.log('\n'); 72 | } 73 | } 74 | 75 | /* 76 | 1 77 | 2 3 78 | 4 5 6 7 79 | 8 9 80 | */ 81 | let tree = new Node(1, new Node(2, new Node(4), new Node(5)), new Node(3, new Node(6, null, new Node(8)), new Node(7, null, new Node(9)))); 82 | printVertical(tree); -------------------------------------------------------------------------------- /printTreeVerticalOp2.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.geeksforgeeks.org/print-binary-tree-vertical-order-set-2/ 3 | */ 4 | 5 | // Node 6 | function Node(val, left, right) { 7 | this.val = val; 8 | this.left = left || null; 9 | this.right = right || null; 10 | } 11 | 12 | /* Keep track of the current level and store it in a hash, the 13 | key is the hd (high distance)*/ 14 | function findDistanceFromRoof(node, hd, hash) { 15 | 16 | // Base case 17 | if(!node) { 18 | return; 19 | } 20 | 21 | // Add the values in the hash 22 | if(hd in hash) { 23 | hash[hd].push(node.val); 24 | }else { 25 | hash[hd] = [node.val]; 26 | } 27 | 28 | //Visit the left and right subtrees 29 | findDistanceFromRoof(node.left, hd - 1, hash); 30 | findDistanceFromRoof(node.right, hd + 1, hash); 31 | } 32 | 33 | 34 | function printVertical(tree) { 35 | let hash = {}; 36 | let level = 0; 37 | 38 | findDistanceFromRoof(tree, level, hash) 39 | // Print by level, the orden is not guaranteed 40 | for(key in hash){ 41 | console.log(hash[key].join(' ')); 42 | } 43 | } 44 | 45 | /* 46 | 1 47 | 2 3 48 | 4 5 6 7 49 | 8 9 50 | */ 51 | let tree = new Node(1, new Node(2, new Node(4), new Node(5)), new Node(3, new Node(6, null, new Node(8)), new Node(7, null, new Node(9)))); 52 | printVertical(tree); 53 | -------------------------------------------------------------------------------- /printTreeVerticalOp3.js: -------------------------------------------------------------------------------- 1 | /* 2 | https://www.geeksforgeeks.org/print-a-binary-tree-in-vertical-order-set-3-using-level-order-traversal/ 3 | */ 4 | 5 | /* 6 | Time Complexity of above implementation is O(n Log n). Note that above implementation uses map which is implemented using self-balancing BST. 7 | 8 | We can reduce time complexity to O(n) using unordered_map. To print nodes in desired order, we can have 2 variables denoting min and max horizontal distance. We can simply iterate from min to max horizontal distance and get corresponding values from Map. So it is O(n) 9 | 10 | Auxiliary Space : O(n) 11 | */ 12 | 13 | // Node 14 | function Node(val, left, right) { 15 | this.val = val; 16 | this.left = left || null; 17 | this.right = right || null; 18 | } 19 | 20 | // function to print vertical order traversal of binary tree 21 | function verticalTraverse(root) { 22 | // Base case 23 | if(!root) { 24 | return; 25 | } 26 | 27 | // Create empty queue for level order traversal 28 | let queue = []; 29 | 30 | // create a map to store nodes at a particular 31 | // horizontal distance 32 | let map = {}; 33 | 34 | // map to store horizontal distance of nodes 35 | let hd_node = {}; 36 | 37 | // enqueue root 38 | queue.push(root) 39 | // store the horizontal distance of root as 0 40 | hd_node[root.val] = 0 41 | 42 | map[0] = [root.val] 43 | 44 | // loop will run while queue is not empty 45 | while (queue.length) { 46 | 47 | // dequeue node from queue 48 | temp = queue.pop(); 49 | 50 | if (temp.left) { 51 | // Enqueue left child 52 | queue.push(temp.left); 53 | 54 | // Store the horizontal distance of left node 55 | // hd(left child) = hd(parent) -1 56 | hd_node[temp.left.val] = hd_node[temp.val] - 1; 57 | hd = hd_node[temp.left.val] 58 | 59 | if(!(hd in map)) { 60 | map[hd] = [temp.left.val]; 61 | } else { 62 | map[hd].push(temp.left.val); 63 | } 64 | } 65 | 66 | if (temp.right) { 67 | // Enqueue right child 68 | queue.push(temp.right); 69 | 70 | // store the horizontal distance of right child 71 | // hd(right child) = hd(parent) + 1 72 | hd_node[temp.right.val] = hd_node[temp.val] + 1; 73 | hd = hd_node[temp.right.val]; 74 | 75 | if(!(hd in map)) { 76 | map[hd] = [temp.right.val]; 77 | } else { 78 | map[hd].push(temp.right.val); 79 | } 80 | } 81 | 82 | } 83 | /* 84 | 0: (3) [1, 6, 5] 85 | 1: (2) [3, 8] 86 | 2: [7] 87 | 3: [9] 88 | -1: [2] 89 | -2: [4] 90 | */ 91 | console.log(map); 92 | /* {1: 0, 2: -1, 3: 1, 4: -2, 5: 0, 6: 0, 7: 2, 8: 1, 9: 3} */ 93 | console.log(hd_node); 94 | // Sort the map according to horizontal distance 95 | sorted_keys = Object.keys(map).map(item => parseInt(item)).sort((a,b) => a - b); 96 | 97 | //Traverse the sorted map and print nodes at each horizontal distance 98 | for(let i = 0; i < sorted_keys.length; i++) { 99 | if(sorted_keys[i] in map) { 100 | console.log(map[sorted_keys[i]]); 101 | } 102 | console.log('\n'); 103 | } 104 | } 105 | 106 | /* 107 | 1 108 | 2 3 109 | 4 5 6 7 110 | 8 9 111 | */ 112 | let tree = new Node(1, new Node(2, new Node(4), new Node(5)), new Node(3, new Node(6, null, new Node(8)), new Node(7, null, new Node(9)))); 113 | verticalTraverse(tree); -------------------------------------------------------------------------------- /randomSubsetOfSizeK.js: -------------------------------------------------------------------------------- 1 | // https://en.wikipedia.org/wiki/Reservoir_sampling#Algorithm_R 2 | // https://www.geeksforgeeks.org/reservoir-sampling/ 3 | // Reservoir Sampling 4 | function randomSubsetOfSizeK(nums, k) { 5 | let result = new Array(k).fill(0); 6 | 7 | // Add the first k into our result 8 | for(let i = 0; i < k; i++) { 9 | result[i] = nums[i]; 10 | } 11 | 12 | for(let i = k; i < nums.length; i++) { 13 | // Random number from 0 to i 14 | let j = Math.floor((Math.random() * i) + 0); 15 | // Replace as we already have the values in the array 16 | if(j < k) { 17 | result[j] = nums[i]; 18 | } 19 | } 20 | 21 | return result; 22 | } 23 | 24 | nums = [2, 6, 56, 32, 46, 567, 23, 56, 13, 67, 678, 123]; 25 | k = 5; 26 | console.log(randomSubsetOfSizeK(nums, k)); -------------------------------------------------------------------------------- /removeInvalidParenthesis.js: -------------------------------------------------------------------------------- 1 | /* 2 | Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results. 3 | 4 | Note: The input string may contain letters other than the parentheses ( and ). 5 | 6 | Example 1: 7 | 8 | Input: "()())()" 9 | Output: ["()()()", "(())()"] 10 | Example 2: 11 | 12 | Input: "(a)())()" 13 | Output: ["(a)()()", "(a())()"] 14 | Example 3: 15 | 16 | Input: ")(" 17 | Output: [""] 18 | 19 | https://leetcode.com/problems/remove-invalid-parentheses/description/ 20 | 21 | */ 22 | 23 | /** 24 | * @param {string} s 25 | * @return {string[]} 26 | */ 27 | 28 | /* 29 | Explanation: 30 | We all know how to check a string of parentheses is valid using a stack. Or even simpler use a counter. 31 | The counter will increase when it is ‘(‘ and decrease when it is ‘)’. Whenever the counter is negative, we have more ‘)’ than ‘(‘ in the prefix. 32 | 33 | To make the prefix valid, we need to remove a ‘)’. The problem is: which one? The answer is any one in the prefix. However, if we remove any one, we will generate duplicate results, for example: s = ()), we can remove s[1] or s[2] but the result is the same (). Thus, we restrict ourself to remove the first ) in a series of concecutive )s. 34 | 35 | After the removal, the prefix is then valid. We then call the function recursively to solve the rest of the string. However, we need to keep another information: the last removal position. If we do not have this position, we will generate duplicate by removing two ‘)’ in two steps only with a different order. 36 | For this, we keep tracking the last removal position and only remove ‘)’ after that. 37 | 38 | Now one may ask. What about ‘(‘? What if s = ‘(()(()’ in which we need remove ‘(‘? 39 | The answer is: do the same from right to left. 40 | However a cleverer idea is: reverse the string and reuse the code! 41 | */ 42 | 43 | //Complexity O(nk) 44 | // n - length of the string 45 | // k - number of recursion calls 46 | var removeInvalidParentheses = function(s) { 47 | let result = []; 48 | remove(s, result, 0, 0, ['(', ')']); 49 | return result; 50 | }; 51 | 52 | function remove(s, result, last_i, last_j, par) { 53 | let stack = 0; 54 | for (let i = last_i; i < s.length; ++i) { 55 | if (s[i] == par[0]) stack++; 56 | if (s[i] == par[1]) stack--; 57 | if (stack >= 0) continue; 58 | for (let j = last_j; j <= i; ++j) 59 | if (s[j] == par[1] && (j == last_j || s[j - 1] != par[1])) { 60 | remove(s.substring(0, j) + s.substring(j + 1, s.length), result, i, j, par); 61 | } 62 | return; // important to avoid a lot of calls! 63 | } 64 | // stack >= 0 : try reverse s and re-do DFS; if already reversed, then add to res 65 | let reversed = s.split('').reverse().join(''); 66 | if (par[0] == '(') // finished left to right 67 | remove(reversed, result, 0, 0, [')', '(']); //Reverse and start again 68 | else { // finished right to left 69 | result.push(reversed); 70 | } 71 | } 72 | 73 | // BFS 74 | var removeInvalidParentheses = function(s) { 75 | let res = []; 76 | if (s == null) return res; 77 | 78 | let queue = []; 79 | let visited = {}; // avoid duplicate results 80 | queue.push(s); 81 | visited[s] = true; 82 | let foundValid = false; 83 | 84 | while (queue.length) { 85 | let t = queue.shift(); 86 | if (isValid(t)) { 87 | res.push(t); 88 | foundValid = true; 89 | } 90 | // found valid, no need to remove anymore, just iterative the rest of queue and add to res when necessary 91 | // As we need to get the elements with the minimum removed characteres required 92 | if (foundValid) continue; 93 | for (let i = 0; i < t.length; i++) { 94 | if(t.charAt(i) != '(' && t.charAt(i) != ')') { 95 | continue; 96 | } 97 | // Remove one by one character on the original string i.e= ()())() - )())() - (())() - ()())() - ()()() - ... 98 | // This will create a lot of options and add them into our queue 99 | let r = t.substring(0, i) + t.substring(i + 1); 100 | if (r in visited) continue; 101 | visited[r] = true; 102 | queue.push(r); 103 | } 104 | } 105 | return res; 106 | } 107 | 108 | function isValid(s) { 109 | let count = 0; // stack variable 110 | for (let i = 0; i < s.length; i++) { 111 | if (s.charAt(i) === '(') count++; 112 | if(s.charAt(i) === ')') count--; 113 | if(count < 0) { 114 | return false; 115 | } 116 | } 117 | return count == 0; 118 | } 119 | 120 | str = "()())()"; 121 | console.log(removeInvalidParentheses(str)); 122 | 123 | // Time O(N), 2 pass 124 | 125 | function removeInvalidParentheses(str) { 126 | let removed = {count: 0}; 127 | let left = remove(str, ['(', ')'], removed); 128 | let reversed = left.split('').reverse().join(''); 129 | let right = remove(reversed, [')', '('], removed); 130 | console.log('Removed:', removed.count); 131 | return right.split('').reverse().join(''); 132 | } 133 | 134 | function remove(str, p, removed) { 135 | let stack = 0; 136 | for(let i = 0; i < str.length; i++) { 137 | if(str[i] === p[0]) stack++; 138 | if(str[i] === p[1]) stack--; 139 | // Unbalance 140 | if(stack < 0) { 141 | removed.count++; 142 | str = str.substring(0, i) + str.substring(i+1); 143 | i--; 144 | stack = 0; 145 | } 146 | } 147 | return str; 148 | } 149 | 150 | 151 | 152 | str = "()())())()" 153 | console.log(removeInvalidParentheses(str)); 154 | 155 | -------------------------------------------------------------------------------- /reverseList.js: -------------------------------------------------------------------------------- 1 | /* 2 | Reverse a singly linked list. 3 | 4 | Example: 5 | 6 | Input: 1->2->3->4->5->NULL 7 | Output: 5->4->3->2->1->NULL 8 | Follow up: 9 | 10 | A linked list can be reversed either iteratively or recursively. Could you implement both? 11 | 12 | https://leetcode.com/problems/reverse-linked-list/description/ 13 | */ 14 | 15 | // iterative 16 | 17 | /** 18 | * Definition for singly-linked list. 19 | * function ListNode(val) { 20 | * this.val = val; 21 | * this.next = null; 22 | * } 23 | */ 24 | var reverseList = function(head) { 25 | let current = head; 26 | let prev = null; 27 | let next 28 | 29 | while(current) { 30 | next = current.next; 31 | current.next = prev; 32 | prev = current; 33 | current = next; 34 | } 35 | 36 | return prev; 37 | }; 38 | 39 | // Recursive Option 1 40 | var reverseList = function(head) { 41 | return helper(head, null); 42 | }; 43 | 44 | function helper(current, newHead) { 45 | if(current === null) return newHead; 46 | let next = current.next; 47 | current.next = newHead; 48 | return helper(next, current); 49 | } 50 | 51 | // Recursive Option 2 52 | 53 | var reverseList = function(head) { 54 | let current = head; 55 | let prev = null; 56 | let next; 57 | 58 | return helper(prev, current, next); 59 | }; 60 | 61 | function helper(prev, current, next) { 62 | if(current) { 63 | next = current.next; 64 | current.next = prev; 65 | prev = current; 66 | current = next; 67 | return helper(prev, current, next) 68 | } 69 | return prev; 70 | } -------------------------------------------------------------------------------- /runLengthEncoding.js: -------------------------------------------------------------------------------- 1 | /* 2 | Run Length Encoding 3 | Given an input string, write a function that returns the Run Length Encoded string for the input string. 4 | For example, if the input string is “wwwwaaadexxxxxx”, then the function should return “w4a3d1e1x6”. 5 | Time: O(n) 6 | */ 7 | function runLength(str) { 8 | let count = 1; 9 | let result = ''; 10 | 11 | for(let i = 0; i < str.length; i++) { 12 | if(str[i] === str[i + 1]) { 13 | count++ 14 | } else { 15 | result += `${str[i]}${count}`; 16 | // Reset values 17 | count = 1; 18 | } 19 | } 20 | return result; 21 | } 22 | 23 | str = "wwwwaaadexxxxxx"; // w4a3d1e1x6 24 | console.log(runLength(str)); 25 | -------------------------------------------------------------------------------- /runningMedians.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | https://www.hackerrank.com/challenges/ctci-find-the-running-median/copy-from/52703266 4 | 5 | */ 6 | 7 | /* 8 | The median of a dataset of integers is the midpoint value of the dataset for which an equal number of integers are less than 9 | and greater than the value. To find the median, you must first sort your dataset of integers in non-decreasing order, then: 10 | 11 | If your dataset contains an odd number of elements, the median is the middle element of the sorted sample. In the sorted 12 | dataset , is the median. 13 | If your dataset contains an even number of elements, the median is the average of the two middle elements of the sorted sample. 14 | In the sorted dataset , is the median. 15 | Given an input stream of integers, you must perform the following task for each integer: 16 | 17 | Add the integer to a running list of integers. 18 | Find the median of the updated list (i.e., for the first element through the element). 19 | Print the list's updated median on a new line. The printed value must be a double-precision number 20 | scaled to decimal place (i.e., format). 21 | Input Format 22 | 23 | The first line contains a single integer, , denoting the number of integers in the data stream. 24 | Each line of the subsequent lines contains an integer, , to be added to your list. 25 | */ 26 | 27 | import java.io.*; 28 | import java.util.*; 29 | import java.text.*; 30 | import java.math.*; 31 | import java.util.regex.*; 32 | 33 | public class Solution { 34 | 35 | public static void printPriorityQueue(PriorityQueue prq){ 36 | // create iterator from the queue 37 | Iterator it = prq.iterator(); 38 | System.out.println ( "Priority queue values are: "); 39 | while (it.hasNext()){ 40 | System.out.println ( "Value: "+ it.next()); 41 | } 42 | } 43 | 44 | public static void main(String[] args) { 45 | Scanner in = new Scanner(System.in); 46 | boolean even = true; 47 | PriorityQueue maxHeap = new PriorityQueue<>((x, y) -> y - x); //Valores menores y me retorna el mayor con peek 48 | PriorityQueue minHeap = new PriorityQueue<>(); //Valores mayores y me retorna el menor con peek 49 | int n = in.nextInt(); 50 | int[] a = new int[n]; 51 | for(int a_i=0; a_i < n; a_i++){ 52 | a[a_i] = in.nextInt(); 53 | } 54 | for(int i = 0; i < a.length; i++){ 55 | /*minHeap es el arbol en donde su root es el menor y todos sus hijos 56 | tienen valores mayores, los valores de minHeap son mayores a los de maxHeap*/ 57 | if(even){ 58 | /*En cada operación debemos insertar en el que no le toca y limpiar*/ 59 | /*De esta manera nos aseuramos que esté balanceado, cuando es par, la 60 | mediana solo es el peek de maxHeap*/ 61 | minHeap.add(a[i]); 62 | int min = minHeap.poll(); 63 | maxHeap.add(min); 64 | double ans = maxHeap.peek(); 65 | System.out.println((double)(ans)); 66 | even = false; 67 | }else{ 68 | /*maxHeap es el arbol en donde su root es el mayor y todos sus hijos 69 | tienen valores menores, maxHeap tienen valores menores a los de maxHeap*/ 70 | /*Cuando es impar sabemos que los dos heaps tienen el mismo tamanio y solo 71 | sacamos el promedio del pick de los dos*/ 72 | maxHeap.add(a[i]); 73 | int max = maxHeap.poll(); 74 | minHeap.add(max); 75 | double ans = (double)(minHeap.peek() + maxHeap.peek())/2; 76 | System.out.println(ans); 77 | even = true; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /searchInSortedArray.js: -------------------------------------------------------------------------------- 1 | /* 2 | Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. 3 | 4 | (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 5 | 6 | You are given a target value to search. If found in the array return its index, otherwise return -1. 7 | 8 | You may assume no duplicate exists in the array. 9 | 10 | https://leetcode.com/problems/search-in-rotated-sorted-array/description/ 11 | 12 | */ 13 | 14 | var search = function(nums, target){ 15 | var start = 0; 16 | var end = nums.length - 1; 17 | var mid = 0; 18 | 19 | while(start <= end){ 20 | mid = Math.floor((start+end)/2); 21 | if (nums[mid] === target) { 22 | return mid; 23 | } else if (nums[start] <= nums[mid]) {// left side sorted 24 | if (nums[mid] > target && nums[start] <= target) { 25 | /*Si el subarray izquierdo esta ordenado, es facil saber 26 | si el elemento se encuentra en esa mitad*/ 27 | // nums[mid] !== target, can safely do end = mid - 1 28 | end = mid - 1; 29 | } else { 30 | //Recorta la seccion a analizar 31 | start = mid + 1; 32 | } 33 | } else { // right side sorted 34 | /*Si no esta ordenado la parte izquierda, la derecha 35 | debe de estar ordenada*/ 36 | if (nums[mid] < target && nums[end] >= target) { 37 | // nums[mid] !== target, can safely do start = mid + 1 38 | start = mid + 1; 39 | } else { 40 | end = mid - 1; 41 | } 42 | } 43 | } 44 | return -1; 45 | } 46 | 47 | array = [4,5,6,7,0,1,2]; 48 | target = 3; 49 | console.log(search(array, target)); 50 | 51 | 52 | //Opcion 2 53 | 54 | var search = function(nums, target) { 55 | let map = {}; 56 | if(nums.length === 0) return -1 57 | nums.forEach((item, index) => map[item] = index); 58 | console.log(map); 59 | //Return result; 60 | if(target in map){ 61 | return map[target]; 62 | }else{ 63 | return -1; 64 | } 65 | }; -------------------------------------------------------------------------------- /serializeAndDeserializeBinaryTree.js: -------------------------------------------------------------------------------- 1 | /* 2 | Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. 3 | 4 | Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure. 5 | 6 | Example: 7 | 8 | You may serialize the following tree: 9 | 10 | 1 11 | / \ 12 | 2 3 13 | / \ 14 | 4 5 15 | 16 | as "[1,2,3,null,null,4,5]" 17 | Clarification: The above format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself. 18 | 19 | Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless. 20 | 21 | https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ 22 | */ 23 | 24 | function TreeNode(val, left, right) { 25 | this.val = val; 26 | this.left = left || null; 27 | this.right = right || null; 28 | } 29 | 30 | // BST 31 | var serialize = function(root) { 32 | if(!root) return ''; 33 | let queue = []; 34 | let result = ''; 35 | 36 | queue.push(root); 37 | 38 | while(queue.length) { 39 | let node = queue.shift(); 40 | 41 | if(!node) { 42 | result = result + 'null '; 43 | continue; 44 | } 45 | 46 | result = result + node.val + ' '; 47 | // Do not check for existence so we can print null too 48 | queue.push(node.left); 49 | queue.push(node.right); 50 | } 51 | 52 | return result.trim(); 53 | }; 54 | 55 | var deserialize = function(data) { 56 | if (data === "") return null; 57 | let queue = []; 58 | 59 | let values = data.split(" "); 60 | let root = new TreeNode(parseInt(values[0])); 61 | queue.push(root); 62 | 63 | for (let i = 1; i < values.length; i++) { 64 | let parent = queue.shift(); 65 | if (values[i] !== "null") { 66 | let left = new TreeNode(parseInt(values[i])); 67 | parent.left = left; 68 | queue.push(left); 69 | } 70 | if (values[++i] !== "null") { 71 | let right = new TreeNode(parseInt(values[i])); 72 | parent.right = right; 73 | queue.push(right); 74 | } 75 | } 76 | return root; 77 | }; 78 | 79 | 80 | tree = new TreeNode(1, new TreeNode(2), new TreeNode(3, new TreeNode(4), new TreeNode(5))); 81 | let str = serialize(tree) 82 | console.log(serialize(str)); 83 | let treeNew = deserialize(str); 84 | console.log(treeNew); -------------------------------------------------------------------------------- /sortColors.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. 3 | 4 | Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. 5 | 6 | Note: 7 | You are not suppose to use the library's sort function for this problem. 8 | 9 | click to show follow up. 10 | 11 | Follow up: 12 | A rather straight forward solution is a two-pass algorithm using counting sort. 13 | First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. 14 | 15 | Could you come up with an one-pass algorithm using only constant space? 16 | 17 | 18 | https://leetcode.com/problems/sort-colors/description/ 19 | */ 20 | //O(N) time complexity and O(1) space complexity 21 | var sortColors = function(nums) { 22 | //Posicion en donde termian las bolas rojas 23 | var redEnds = 0; 24 | //Las ultimas posiciones son para las bolas azules 25 | var blueStars = nums.length -1 26 | 27 | //Empieza el loop para ordenar las bolas 28 | for(var i = 0; i <= blueStars; ){ 29 | if(nums[i] === 0){ 30 | //Hacemos swao 31 | swap(redEnds, i, nums); 32 | //Incrementamos en donde terminan las bolas rojas 33 | redEnds++; 34 | //Incrementamos i 35 | i++; 36 | }else if(nums[i] === 2){ 37 | //Hacemos swap 38 | swap(blueStars, i, nums); 39 | //Decrementamos la posicion en donde empiezan las bolas azules 40 | blueStars--; 41 | }else{ 42 | i++; 43 | } 44 | } 45 | return nums; 46 | }; 47 | 48 | function swap(a,b, array){ 49 | var tmp = array[a]; 50 | array[a] = array[b]; 51 | array[b] = tmp; 52 | } 53 | 54 | // Option 2 55 | var sortColors = function(nums) { 56 | var redEnds = 0; 57 | var blueStars = nums.length -1 58 | 59 | //Empieza el loop para ordenar las bolas 60 | let i = 0; 61 | while(i <= blueStars){ 62 | if(nums[i] === 0){ 63 | swap(redEnds, i, nums); 64 | redEnds++; 65 | i++; 66 | }else if(nums[i] === 2){ 67 | swap(blueStars, i, nums); 68 | blueStars--; 69 | }else{ 70 | i++; 71 | } 72 | } 73 | console.log(nums); 74 | }; 75 | 76 | function swap(a,b, array){ 77 | var tmp = array[a]; 78 | array[a] = array[b]; 79 | array[b] = tmp; 80 | } 81 | 82 | var sortColors = function(nums) { 83 | let result = []; 84 | let count0 = 0; 85 | let count1 = 0; 86 | let count2 = 0; 87 | let tmp = 0; 88 | 89 | for(let i = 0; i < nums.length; i++) { 90 | if(nums[i] === 0) { 91 | count0++; 92 | } 93 | if(nums[i] === 1) { 94 | count1++; 95 | } 96 | if(nums[i] === 2) { 97 | count2++; 98 | } 99 | } 100 | 101 | // Set 0's 102 | for(let i = 0; i < count0; i++) { 103 | result[tmp++] = 0; 104 | } 105 | 106 | // Set 1´s 107 | for(let i = 0; i < count1; i++) { 108 | result[tmp++] = 1; 109 | } 110 | 111 | // Set 2´s 112 | for(let i = 0; i < count2; i++) { 113 | result[tmp++] = 2; 114 | } 115 | 116 | console.log(result); 117 | 118 | return result; 119 | } 120 | 121 | 122 | //var array = [0,1,2,2,0,1,2,0,1,1,2]; 123 | var array = [1,2,0]; 124 | console.log(sortColors(array)); -------------------------------------------------------------------------------- /squaresOfASortedArray.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers A sorted in non-decreasing order, return an array of the squares of each number, also 3 | in sorted non-decreasing order. 4 | 5 | Example 1: 6 | 7 | Input: [-4,-1,0,3,10] 8 | Output: [0,1,9,16,100] 9 | Example 2: 10 | 11 | Input: [-7,-3,2,3,11] 12 | Output: [4,9,9,49,121] 13 | 14 | 15 | Note: 16 | 17 | 1 <= A.length <= 10000 18 | -10000 <= A[i] <= 10000 19 | A is sorted in non-decreasing order. 20 | 21 | 22 | https://leetcode.com/articles/squares-of-a-sorted-array/ 23 | */ 24 | 25 | // Opción 1 26 | // Two pointer 27 | // Time Complexity: O(N) where N is the length of A. 28 | // Space Complexity: O(N) 29 | /* 30 | Intuition 31 | 32 | Since the array A is sorted, loosely speaking it has some negative elements with squares in decreasing order, 33 | then some non-negative elements with squares in increasing order. 34 | 35 | For example, with [-3, -2, -1, 4, 5, 6], we have the negative part [-3, -2, -1] with squares [9, 4, 1], and the 36 | positive part [4, 5, 6] with squares [16, 25, 36]. Our strategy is to iterate over the negative part in reverse, and 37 | the positive part in the forward direction. 38 | 39 | Algorithm: 40 | We can use two pointers to read the positive and negative parts of the array - one pointer j in the positive direction, and another i in the negative direction. 41 | Now that we are reading two increasing arrays (the squares of the elements), we can merge these arrays together using a two-pointer technique. 42 | */ 43 | function sortedSquares(array) { 44 | let result = []; 45 | let j = 0; 46 | 47 | while(j < array.length && array[j] < 0) { 48 | j++; 49 | } 50 | 51 | let i = j - 1; 52 | let index = 0; 53 | 54 | while(i >= 0 && j < array.length) { 55 | if(array[i] * array[i] < array[j] * array[j]) { 56 | result[index++] = array[i] * array[i]; 57 | i--; 58 | } else { 59 | result[index++] = array[j] * array[j]; 60 | j++; 61 | } 62 | } 63 | 64 | // If we have missing values 65 | while (i >= 0) { 66 | result[index++] = array[i] * array[i]; 67 | i--; 68 | } 69 | 70 | while (j < array.length) { 71 | result[index++] = array[j] * array[j]; 72 | j++; 73 | } 74 | 75 | return result; 76 | } 77 | 78 | // Opción 2 79 | // Time Complexity: O(Nlog N) where N is the length of A. 80 | // Space Complexity: O(N) 81 | function sortedSquares(array) { 82 | let result = []; 83 | for(let i = 0; i < array.length; i++) { 84 | result[i] = array[i] * array[i]; 85 | } 86 | return result.sort((a,b) => a - b); 87 | } 88 | 89 | array = [-4,-1,0,3,10]; 90 | console.log(sortedSquares(array)); -------------------------------------------------------------------------------- /strStr.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Implement strStr(). 4 | 5 | Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 6 | 7 | Example 1: 8 | 9 | Input: haystack = "hello", needle = "ll" 10 | Output: 2 11 | Example 2: 12 | 13 | Input: haystack = "aaaaa", needle = "bba" 14 | Output: -1 15 | Clarification: 16 | 17 | What should we return when needle is an empty string? This is a great question to ask during an interview. 18 | 19 | For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf(). 20 | 21 | 22 | https://leetcode.com/problems/implement-strstr/description/ 23 | */ 24 | 25 | var strStr = function(haystack, needle) { 26 | if(haystack.length === needle.length) return haystack === needle ? 0 : -1; 27 | if(needle.length === 0) return 0; 28 | if(haystack.length < needle.length) return -1; 29 | 30 | let first = needle[0]; 31 | for(let i = 0; i < haystack.length; i++) { 32 | if(haystack[i] === first) { 33 | let j = 1 34 | for(; j < needle.length; j++) { 35 | if(haystack[i + j] !== needle[j]) { 36 | break; 37 | } 38 | } 39 | if(j === needle.length) { 40 | return i; 41 | } 42 | } 43 | } 44 | return -1; 45 | }; 46 | 47 | var strStr = function(haystack, needle) { 48 | let result = 0; 49 | let firstLetter = needle[0]; 50 | let tamStr = needle.length; 51 | if(haystack === "" && needle !== "") return -1; 52 | if(needle === "") return 0; 53 | for(let i = 0; i < haystack.length; i++){ 54 | if(haystack[i] === firstLetter){ 55 | /*En slice incluye la primera posición pero no la 56 | última y como es 0-based, está en lo correcto*/ 57 | if(haystack.slice(i, i + tamStr) === needle){ 58 | return i; 59 | } 60 | } 61 | } 62 | return -1; 63 | }; 64 | 65 | haystack = "mississippi"; 66 | needle = "issip"; 67 | console.log(strStr(haystack, needle)); -------------------------------------------------------------------------------- /subset II.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a collection of integers that might contain duplicates, nums, return all possible subsets. 3 | 4 | Note: The solution set must not contain duplicate subsets. 5 | 6 | For example, 7 | If nums = [1,2,2], a solution is: 8 | 9 | [ 10 | [2], 11 | [1], 12 | [1,2,2], 13 | [2,2], 14 | [1,2], 15 | [] 16 | ] 17 | 18 | https://leetcode.com/problems/subsets-ii/description/ 19 | */ 20 | 21 | // Opción 1 22 | var subsetsWithDup = function(nums) { 23 | let result = []; 24 | // Sort to make easier to detect duplicates 25 | nums.sort((a,b) => a-b); 26 | dfs(result, [], 0, nums.length, nums); 27 | return result; 28 | }; 29 | 30 | function dfs(result, tmp, start, end, nums) { 31 | result.push(tmp); 32 | for(let i = start; i < end; i++) { 33 | // Skip duplicates 34 | if(i > start && nums[i] === nums[i-1]) { 35 | continue; 36 | } 37 | tmp.push(nums[i]); 38 | dfs(result, tmp.concat(), i + 1, end, nums); 39 | tmp.pop(); 40 | } 41 | } 42 | 43 | // Opción 2 44 | var subsetsWithDup = function(nums) { 45 | var result = []; 46 | if(nums.length === 0) return result; 47 | //In case is not sorted 48 | /*Asi no habra duplicados*/ 49 | nums.sort((a,b) => a-b); 50 | helper(result, [], 0, nums.length-1, nums); 51 | return result; 52 | }; 53 | 54 | function helper(result, currArr, start, end, nums){ 55 | result.push(currArr); 56 | for(let i = start; i <= end; i++){ 57 | //Skip duplicates 58 | if(i > start && nums[i] === nums[i-1]){ 59 | continue; 60 | } 61 | currArr.push(nums[i]); 62 | helper(result, currArr.concat(), i+1, end, nums); 63 | currArr.pop(); 64 | } 65 | } 66 | 67 | nums = [1,2,2] 68 | console.log(subsetsWithDup(nums)); 69 | -------------------------------------------------------------------------------- /taskScheduler.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks. 3 | Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle. 4 | 5 | However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals 6 | that CPU are doing different tasks or just be idle. 7 | 8 | You need to return the least number of intervals the CPU will take to finish all the given tasks. 9 | 10 | Example: 11 | 12 | Input: tasks = ["A","A","A","B","B","B"], n = 2 13 | Output: 8 14 | Explanation: A -> B -> idle -> A -> B -> idle -> A -> B. 15 | 16 | Greedy Approach 17 | https://www.youtube.com/watch?v=ySTQCRya6B0 18 | https://leetcode.com/articles/task-scheduler/ 19 | */ 20 | 21 | class Solution { 22 | public int leastInterval(char[] tasks, int n) { 23 | // Greedy Approach 24 | // https://www.youtube.com/watch?v=ySTQCRya6B0 25 | // https://leetcode.com/articles/task-scheduler/ 26 | HashMap map = new HashMap<>(); 27 | for(char c: tasks) { 28 | map.put(c, map.getOrDefault(c, 0) + 1); 29 | } 30 | 31 | // Get the max element under the maxHeap in constant time 32 | PriorityQueue maxHeap = new PriorityQueue<>((a,b) -> b -a); 33 | // Throw all values into the max heap 34 | maxHeap.addAll(map.values()); 35 | 36 | int cycles = 0; 37 | 38 | while(!maxHeap.isEmpty()) { 39 | List tmp = new ArrayList<>(); 40 | for(int i = 0; i <= n; i++) { 41 | if(!maxHeap.isEmpty()) { 42 | tmp.add(maxHeap.remove()); 43 | } 44 | } 45 | 46 | // Decrement the process and check if we still need to process more cycles 47 | // for example if A is 3, we need to process A, 3 times 48 | for(int i : tmp) { 49 | if(--i > 0) { 50 | maxHeap.add(i); 51 | } 52 | } 53 | 54 | // n is the cool down 55 | cycles += maxHeap.isEmpty() ? tmp.size() : n + 1; 56 | } 57 | 58 | return cycles; 59 | } 60 | } -------------------------------------------------------------------------------- /treePathsSum.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, where every node value is a Digit from 1-9 .Find the sum of all the numbers which are formed from root to leaf paths. 3 | For example consider the following Binary Tree. 4 | 5 | 6 6 | / \ 7 | 3 5 8 | / \ \ 9 | 2 5 4 10 | / \ 11 | 7 4 12 | There are 4 leaves, hence 4 root to leaf paths: 13 | Path Number 14 | 6->3->2 632 15 | 6->3->5->7 6357 16 | 6->3->5->4 6354 17 | 6->5>4 654 18 | Answer = 632 + 6357 + 6354 + 654 = 13997 19 | 20 | https://www.geeksforgeeks.org/sum-numbers-formed-root-leaf-paths/ 21 | */ 22 | 23 | function TreeNode(val, left, right) { 24 | this.val = val; 25 | this.left = left || null; 26 | this.right = right || null; 27 | } 28 | 29 | function treePathsSum(root) { 30 | return helper(root, 0); 31 | } 32 | 33 | // Traverse inorder 34 | function helper(node, val) { 35 | 36 | // Base case 37 | if(!node) return 0; 38 | 39 | // Update value 40 | val = (val * 10) + node.val; 41 | 42 | // Check if we reach leaf node to return the value 43 | if(!node.left && !node.right) { 44 | return val; 45 | } 46 | 47 | return helper(node.left, val) + helper(node.right, val); 48 | } 49 | 50 | 51 | tree = new TreeNode(6, new TreeNode(3, new TreeNode(2), new TreeNode(5, new TreeNode(7), new TreeNode(4))), new TreeNode(5, null, new TreeNode(4))); 52 | console.log(treePathsSum(tree)); -------------------------------------------------------------------------------- /validPalindrome.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. 3 | 4 | Note: For the purpose of this problem, we define empty string as valid palindrome. 5 | 6 | Example 1: 7 | 8 | Input: "A man, a plan, a canal: Panama" 9 | Output: true 10 | Example 2: 11 | 12 | Input: "race a car" 13 | Output: false 14 | 15 | https://leetcode.com/problems/valid-palindrome/description/ 16 | */ 17 | 18 | /** 19 | * @param {string} s 20 | * @return {boolean} 21 | */ 22 | var isPalindrome = function (s) { 23 | let left = 0; 24 | let right = s.length - 1; 25 | let alphanumeric = /^[a-z0-9]+$/i; 26 | 27 | while (left < right) { 28 | // Skip non-alphanumeric chars 29 | while (left < right && !alphanumeric.test(s[left])) { 30 | left++; 31 | } 32 | 33 | // Skip non-alphanumeric chars 34 | while (left < right && !alphanumeric.test(s[right])) { 35 | right--; 36 | } 37 | 38 | if (s[left++].toLowerCase() !== s[right--].toLowerCase()) { 39 | return false; 40 | } 41 | } 42 | return true; 43 | }; -------------------------------------------------------------------------------- /weightedRandomNumbers.js: -------------------------------------------------------------------------------- 1 | /*Generar números aleatorios en base a una probabilidad 2 | 3 | http://www.geeksforgeeks.org/random-number-generator-in-arbitrary-probability-distribution-fashion/ 4 | 5 | */ 6 | 7 | /*A(1), B(1), C(2) es lo mismo que [A,B,C,C] con numeros 8 | de frecuencia muy altos es costoso porque necesitamos mucho espacio*/ 9 | 10 | 11 | //O(logN) 12 | function generateRandom(arr, freq){ 13 | let n = arr.length; 14 | //Create prefix 15 | let prefix = new Array(n).fill(0); 16 | let sum = 0; 17 | for(let i = 0; i < n; i++){ 18 | sum += freq[i]; 19 | prefix[i] = sum; 20 | } 21 | /*Los prefix denotan el punto maximo de cada valor para 22 | que el aleatorio entre en ese rango ejemplo si tenemos el 23 | array como [1,2,3,4] y el prefix [10,15,75,175] y 24 | llega un 45 de random, el valor entra dentro del 3*/ 25 | console.log(prefix); 26 | /*prefix[n-1] es la suma de todas las frecuencias. Generamos 27 | un numero random de 1 a este numero*/ 28 | let random = Math.floor(Math.random() * prefix[n-1]); 29 | console.log(random); 30 | 31 | //Buscamos el index de random en el prefix array 32 | let index = findCeil(prefix, random, 0, n-1); 33 | return arr[index]; 34 | } 35 | 36 | function findCeil(prefix, random, start, end){ 37 | let mid; 38 | //Binary Search 39 | while(start < end){ 40 | mid = Math.floor((start + end)/2); 41 | if(random > prefix[mid]){ 42 | start = mid + 1; 43 | }else{ 44 | end = mid; 45 | } 46 | } 47 | /*Start contiene el index en donde cae el numero que 48 | se mostrara en el arreglo principal*/ 49 | return prefix[start] >= random ? start : -1; 50 | } 51 | 52 | function main(arr, freq){ 53 | for(let i = 0; i < arr.length; i++){ 54 | console.log(generateRandom(arr,freq)); 55 | } 56 | } 57 | 58 | var arr = [1, 2, 3, 4]; 59 | var freq = [10, 5, 60, 100]; 60 | main(arr, freq); 61 | 62 | -------------------------------------------------------------------------------- /wordBreak.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a 3 | space-separated sequence of one or more dictionary words. You may assume the dictionary does not contain duplicate words. 4 | 5 | For example, given 6 | s = "leetcode", 7 | dict = ["leet", "code"]. 8 | 9 | Return true because "leetcode" can be segmented as "leet code". 10 | 11 | UPDATE (2017/1/4): 12 | The wordDict parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to 13 | get the latest changes. 14 | 15 | https://leetcode.com/problems/word-break/description/ 16 | https://www.programcreek.com/2012/12/leetcode-solution-word-break/ 17 | https://youtu.be/WepWFGxiwRs 18 | */ 19 | 20 | // O(n^2) en tiempo y memoria O(n) 21 | // Best option. 22 | function wordBreak(str, dict) { 23 | let n = str.length; 24 | if(!str || n === 0) { 25 | return false; 26 | } 27 | 28 | let dp = new Array(n+1).fill(false); 29 | dp[0] = true; 30 | 31 | for(let i = 1; i < n+1; i++) { 32 | for(let j = 0; j <= i; j++) { 33 | // El dp[j] nos ayuda a identificar si las partes anteriores fueron encontradas, 34 | // el substring como es 0 based nos ayuda a recortar la cadena correcta 35 | if(dp[j] && dict.includes(str.substring(j,i))) { 36 | dp[i] = true; 37 | break; 38 | } 39 | } 40 | } 41 | 42 | console.log(dp); 43 | return dp[n]; 44 | } 45 | 46 | str = 'leetcode'; 47 | dict = ['leet', 'code']; 48 | console.log(wordBreak(str, dict)); 49 | 50 | var wordBreak = function(str, dic) { 51 | let pos = new Array(str.length+1).fill(-1); 52 | pos[0]=0; 53 | for(let i = 0; i < str.length; i++){ 54 | if(pos[i] !== -1){ 55 | for(let j = i + 1; j <= str.length; j++){ 56 | let sub = str.substring(i, j); 57 | if(dic.indexOf(sub) >= 0){ 58 | pos[j]=i; 59 | } 60 | } 61 | } 62 | } 63 | /*Si el final es distinto de cero entonces hemos formado 64 | la palabra*/ 65 | return pos[str.length] !== -1; 66 | }; 67 | 68 | s = "leetcode"; 69 | dict = ["leet", "code"]; 70 | console.log(wordBreak(s,dict)); 71 | -------------------------------------------------------------------------------- /wordDictionaryTrie.js: -------------------------------------------------------------------------------- 1 | /* 2 | Design a data structure that supports the following two operations: 3 | 4 | void addWord(word) 5 | bool search(word) 6 | search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter. 7 | 8 | Example: 9 | 10 | addWord("bad") 11 | addWord("dad") 12 | addWord("mad") 13 | search("pad") -> false 14 | search("bad") -> true 15 | search(".ad") -> true 16 | search("b..") -> true 17 | Note: 18 | You may assume that all words are consist of lowercase letters a-z. 19 | 20 | https://leetcode.com/problems/add-and-search-word-data-structure-design/description/ 21 | */ 22 | 23 | /** 24 | * Initialize your data structure here. 25 | */ 26 | 27 | var WordDictionary = function () { 28 | this.trie = { children: {}, count: 0, isWord: false }; 29 | }; 30 | 31 | /** 32 | * Adds a word into the data structure. 33 | * @param {string} word 34 | * @return {void} 35 | */ 36 | WordDictionary.prototype.addWord = function (word) { 37 | let node = this.trie; 38 | for (let i = 0; i < word.length; i++) { 39 | //Asigna el nodo si lo encuentra o agrega un elemento para agregarlo al trie 40 | node.children[word[i]] = node.children[word[i]] || { 41 | children: {}, 42 | count: 0, 43 | isWord: false, 44 | }; 45 | // Recorre el nodo 46 | node = node.children[word[i]]; 47 | // Cuenta las veces que se ha visto 48 | node.count++; 49 | } 50 | // Marca el end de la palabra 51 | node.isWord = true; 52 | }; 53 | 54 | /** 55 | * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. 56 | * @param {string} word 57 | * @return {boolean} 58 | */ 59 | WordDictionary.prototype.search = function (word) { 60 | let node = this.trie; 61 | return this.dfs(word, 0, node); 62 | }; 63 | 64 | // da 65 | /* 66 | { 67 | d: { 68 | a: { 69 | d 70 | } 71 | } 72 | 73 | } 74 | */ 75 | WordDictionary.prototype.dfs = function (word, start, node) { 76 | // We need to verify the existence of node cause we 77 | // may be sending undefined values checking for the '.' 78 | if (start === word.length && node) { 79 | return node.isWord; 80 | } 81 | let c = word[start]; 82 | if (c === ".") { 83 | // Check all possible letters in the alphabet to find is there is a word 84 | for (let i = 0; i < 26; i++) { 85 | let letter = String.fromCharCode("a".charCodeAt(0) + i); 86 | if ( 87 | node && 88 | node.children[letter] && 89 | this.dfs(word, start + 1, node.children[letter]) 90 | ) { 91 | return true; 92 | } 93 | } 94 | } else { 95 | if (node && node.children[c]) { 96 | return this.dfs(word, start + 1, node.children[c]); 97 | } 98 | } 99 | 100 | return false; 101 | }; 102 | 103 | /** 104 | * Your WordDictionary object will be instantiated and called as such: 105 | * var obj = Object.create(WordDictionary).createNew() 106 | * obj.addWord(word) 107 | * var param_2 = obj.search(word) 108 | */ 109 | 110 | var obj = new WordDictionary(); // Object.create(WordDictionary); //.createNew(); 111 | obj.addWord("bad"); 112 | obj.addWord("dad"); 113 | obj.addWord("mad"); 114 | console.log(obj); 115 | console.log(obj.search("pad")); // -> false 116 | console.log(obj.search("bad")); // -> true 117 | console.log(obj.search(".ad")); // -> true 118 | console.log(obj.search("b..")); // -> true 119 | --------------------------------------------------------------------------------