├── excercises ├── hasDuplicates.js ├── longestSubstring.js └── luckyInteger.js ├── frequency_counters ├── anagram.js └── frequencyCounter.js ├── multiple_pointers ├── naive_approach.js ├── solution_approach.js └── unique_values.js └── sliding_window ├── naive_approach.js └── solution_approach.js /excercises/hasDuplicates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement a function called hasDuplicates which accepts 3 | * a variable number of integer arguments and returns 4 | * true if there are duplicates in the arguments. 5 | * 6 | * Should be solved in O(n) or better. 7 | * 8 | */ 9 | 10 | /* Pseudo code 11 | -function should be called hasDuplicates 12 | -function should accept n number of arguments 13 | -return boolean TRUE if duplicates are found and otherwise FALSE 14 | -should be have a Big O(N) or better 15 | */ 16 | 17 | function hasDuplicates(...args) { 18 | const counter = {}; 19 | 20 | for (let val of args) { 21 | if (!counter[val]) { 22 | counter[val] = 1; 23 | } else { 24 | return true; 25 | } 26 | } 27 | 28 | return false; 29 | } 30 | 31 | console.log(hasDuplicates(1, 2, 3, 4, 5, 6)); 32 | console.log(hasDuplicates(-1, -2, -3, -4, 4, 5, 6)); 33 | console.log(hasDuplicates(1, 2, 3, 4, 5, 6, 6)); 34 | console.log(hasDuplicates(1, 1, 1, 2, 3, 4, 5, 6)); 35 | -------------------------------------------------------------------------------- /excercises/longestSubstring.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnMwendwa/03-problem-solving-patterns/1e7af9203c6c64648a7c39c3efda9b18421383fa/excercises/longestSubstring.js -------------------------------------------------------------------------------- /excercises/luckyInteger.js: -------------------------------------------------------------------------------- 1 | /* 2 | PROBLEM STATEMENT 3 | ========================================================================================= 4 | Given an array of integers arr, a lucky integer is an integer that has a frequency in the array equal to its value. 5 | 6 | Return the largest lucky integer in the array. If there is no lucky integer return -1. 7 | ======================================================================================= 8 | */ 9 | 10 | /* Pseudo code 11 | -function should accept an array as argument 12 | -Argument name is arr 13 | -lucky integer is an integer that appears equal times its value 14 | -the largest lucky integer should be returned 15 | -If there is no lucky integer, return -1 16 | 17 | ------------------------------------------------------ 18 | -function wiil be called findLuckyInteger 19 | -Create an empty object 20 | -Create a variable to track max value 21 | -Loop through the array as you assign each unique value a value 22 | -Loop again and search the integer that has max equal key - value 23 | -return its key or -1 if it's not found 24 | 25 | */ 26 | 27 | function findLuckyInteger(arr) { 28 | const luckyCounter = {}; 29 | let maxValue = 0; 30 | 31 | for (let val of arr) { 32 | luckyCounter[val] = (luckyCounter[val] || 0) + 1; 33 | } 34 | 35 | for (let key in luckyCounter) { 36 | if (luckyCounter[key] === parseInt(key)) { 37 | maxValue = parseInt(key); 38 | } 39 | } 40 | 41 | if (maxValue > 0) { 42 | return maxValue; 43 | } else { 44 | return -1; 45 | } 46 | } 47 | 48 | console.log(findLuckyInteger([2, 2, 3, 4])); // 2 49 | console.log(findLuckyInteger([1, 2, 2, 3, 3, 3])); // 3 50 | console.log(findLuckyInteger([2, 2, 2, 3, 3])); // -1 51 | -------------------------------------------------------------------------------- /frequency_counters/anagram.js: -------------------------------------------------------------------------------- 1 | // Given two strings, write a function to determine if the second string is an angram of the first.An anagram is a word, phrase, or name formed by rearranging the letters of another, such as cinema, formed from iceman. 2 | 3 | /* 4 | validAnagram("","") //true 5 | validAnagram('aaz',"zza") //false 6 | validAnagram("anagram","nagaram") //true 7 | validAnagram("rat","car") //false 8 | validAnagram("awesome","awesom") //false 9 | validAnagram("qwerty","qeywrt") //true 10 | */ 11 | 12 | /* 13 | -There are 2 string args: str1, str2 14 | -Both strings should have equal number of characters 15 | -lowercase the strings 16 | */ 17 | 18 | // my solution 19 | function validAnagram(str1, str2) { 20 | // should have same number of characters 21 | if (str1.length !== str2.length) return false; 22 | let counter1 = {}; 23 | let counter2 = {}; 24 | 25 | for (let val of str1) { 26 | counter1[val] = (counter1[val] || 0) + 1; 27 | } 28 | for (let val of str2) { 29 | counter2[val] = (counter2[val] || 0) + 1; 30 | } 31 | 32 | for (let key in counter1) { 33 | if (!(key in counter2)) { 34 | return false; 35 | } 36 | if (counter1[key] !== counter2[key]) { 37 | return false; 38 | } 39 | } 40 | 41 | return true; 42 | } 43 | 44 | // colt steele solution 45 | function validAnagram(str1, str2) { 46 | if (str1.length !== str2.length) { 47 | return false; 48 | } 49 | 50 | let counter = {}; 51 | 52 | for (let val of str1) { 53 | counter[val] = (counter[val] || 0) + 1; 54 | } 55 | 56 | for (let val of str2) { 57 | if (!counter[val]) { 58 | return false; 59 | } else { 60 | console.log(counter); 61 | counter[val] -= 1; 62 | } 63 | } 64 | return true; 65 | } 66 | 67 | console.log(validAnagram("anagram", "nagara")); 68 | console.log(validAnagram("anagamr", "nagaram")); 69 | -------------------------------------------------------------------------------- /frequency_counters/frequencyCounter.js: -------------------------------------------------------------------------------- 1 | // Write a function called same, which accepts two arrays.The function should return true if every value in the array has its corresponding value squared in the second array.The frequency of values must be the same. 2 | 3 | /*Pseudo code Solution 4 | - function should only accept 2 arrays 5 | - both arrays length must be equal 6 | - function should return a boolean 7 | - value in second array are squares of the first 8 | - variables used will be arr1, array2 9 | */ 10 | 11 | // My first solution 12 | function same(arr1, arr2) { 13 | // check if both arguments are valid arrays 14 | if (!Array.isArray(arr1) || !Array.isArray(arr2)) { 15 | return false; 16 | } else if (arr1.length !== arr2.length) { 17 | return false; 18 | } 19 | 20 | // square the values in arr1 21 | const array1Sorted = arr1.map((v) => v * v).sort(); 22 | const array2Sorted = arr2.sort(); 23 | return array1Sorted.toString() === array2Sorted.toString(); 24 | } 25 | 26 | // Colt steele naive solution - O(N^2) 27 | function same(arr1, arr2) { 28 | // check if both arrays have same length 29 | if (arr1.length !== arr2.length) { 30 | return false; 31 | } 32 | 33 | for (let i = 0; i < arr1.length; i++) { 34 | let correctIndex = arr2.indexOf(arr1[i] ** 2); 35 | console.log(correctIndex); 36 | if (correctIndex === -1) { 37 | return false; 38 | } 39 | arr2.splice(correctIndex, 1); 40 | } 41 | return true; 42 | } 43 | 44 | // colt steele final refactored solution - O(N) 45 | function same(arr1, arr2) { 46 | // check if both arrays have same length 47 | if (arr1.length !== arr2.length) { 48 | return false; 49 | } 50 | 51 | let frequencyCounter1 = {}; 52 | let frequencyCounter2 = {}; 53 | 54 | for (let val of arr1) { 55 | frequencyCounter1[val] = (frequencyCounter1[val] || 0) + 1; 56 | } 57 | 58 | for (let val of arr2) { 59 | frequencyCounter2[val] = (frequencyCounter2[val] || 0) + 1; 60 | } 61 | 62 | for (let key in frequencyCounter1) { 63 | // check if a key is missing in any of the 2 arrays 64 | if (!(key ** 2 in frequencyCounter2)) { 65 | return false; 66 | } 67 | 68 | // check if the values of keys are equal in both arrays 69 | if (frequencyCounter2[key ** 2] !== frequencyCounter1[key]) { 70 | return false; 71 | } 72 | } 73 | return true; 74 | } 75 | 76 | const value1 = [3, 2, 1, 1]; 77 | const value2 = [4, 1, 9, 1]; 78 | console.log(same(value1, value2)); 79 | -------------------------------------------------------------------------------- /multiple_pointers/naive_approach.js: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Write a function called sumZero which accepts a sorted array of integers.The function should find the first pair where the sum is 0. Return an array the includes both values that sum to zero or undefined if a pair does not exist. 3 | 4 | sumZero([-3,-2,-1,0,1,2,3]) // [-3,3] 5 | sumZero([-2,0,1,3]) // undefined 6 | sumZero([1,2,3]) // undefined 7 | ============================================================================= 8 | */ 9 | 10 | // O(n^2) 11 | function sumZero(arr) { 12 | for (let i = 0; i < arr.length; i++) { 13 | for (let j = i + 1; j < arr.length; j++) { 14 | if (arr[i] + arr[j] === 0) { 15 | return [arr[i], arr[j]]; 16 | } 17 | } 18 | } 19 | } 20 | 21 | console.log(sumZero([-3, -2, -1, 0, 1, 2, 3])); // [-3,3] 22 | console.log(sumZero([-2, 0, 1, 3])); // undefined 23 | console.log(sumZero([1, 2, 3])); // undefined 24 | -------------------------------------------------------------------------------- /multiple_pointers/solution_approach.js: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Write a function called sumZero which accepts a sorted array of integers.The function should find the first pair where the sum is 0. Return an array the includes both values that sum to zero or undefined if a pair does not exist. 3 | 4 | sumZero([-3,-2,-1,0,1,2,3]) // [-3,3] 5 | sumZero([-2,0,1,3]) // undefined 6 | sumZero([1,2,3]) // undefined 7 | ============================================================================= 8 | */ 9 | 10 | function sumZero(arr) { 11 | let left = 0; 12 | let right = arr.length - 1; 13 | 14 | while (left < right) { 15 | let sum = arr[left] + arr[right]; 16 | //if sum is 0 stop the loop 17 | if (sum === 0) { 18 | return [arr[left], arr[right]]; 19 | //subtract from the right if sum is greater than 0 20 | } else if (sum > 0) { 21 | right--; 22 | //subtract from the left if sum is less than 0 23 | } else { 24 | left++; 25 | } 26 | } 27 | } 28 | 29 | console.log(sumZero([-3, -2, -1, 0, 1, 2, 3])); // [-3,3] 30 | console.log(sumZero([-2, 0, 1, 3])); // undefined 31 | console.log(sumZero([1, 2, 3])); // undefined 32 | -------------------------------------------------------------------------------- /multiple_pointers/unique_values.js: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Implement a function called countUniqueValues, which accepts a sorted array, and counts the unique values in the array. There can be negative numbers in the array, but it will always be sorted. 3 | 4 | countUniqueValues([1,1,1,1,1,2]) //2 5 | countUniqueValues([1,2,3,4,4,4,7,7,12,12,13]) //2 6 | countUniqueValues([]) //0 7 | countUniqueValues([-2,-1,-1,0,1]) //4 8 | ============================================================================= 9 | */ 10 | 11 | /* PSEUDO CODE SOULTION 12 | -function name will be counteUniqueValues 13 | -argument will be named arr 14 | -function should accept a sorted array 15 | -function should only count the unique values in the array and return the total count 16 | 17 | ---------------------------------- 18 | -Return 0 if array is empty 19 | -Initialize a variable to track the unique values 20 | -Loop over the array from left side noting and adding the unique values to the variable 21 | */ 22 | 23 | // My solution 24 | function countUniqueValues(arr) { 25 | if (arr.length === 0) return 0; 26 | let left = 0; 27 | let right = 0; 28 | let count = 0; 29 | while (right < arr.length) { 30 | right = left + 1; 31 | if (arr[left] === arr[right]) { 32 | left += 1; 33 | } else { 34 | left += 1; 35 | count += 1; 36 | } 37 | } 38 | return count; 39 | } 40 | 41 | // colt steele solution 42 | function countUniqueValues(arr) { 43 | if (arr.length === 0) return 0; 44 | let i = 0; 45 | for (let j = 1; j < arr.length; j++) { 46 | if (arr[i] !== arr[j]) { 47 | i++; 48 | arr[i] = arr[j]; 49 | } 50 | } 51 | return i + 1; 52 | } 53 | 54 | console.log(countUniqueValues([1, 1, 1, 1, 1, 2])); //2 55 | console.log(countUniqueValues([1, 2, 3, 4, 4, 4, 7, 7, 12, 12, 13])); // 56 | console.log(countUniqueValues([])); //0 57 | console.log(countUniqueValues([-2, -1, -1, 0, 1])); //4 58 | -------------------------------------------------------------------------------- /sliding_window/naive_approach.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Write a function called maxSubarraySum which accepts an array of integers and a number called n. The function should calculate the maximum sum of n consecutive elements in the array. 4 | 5 | maxSubarraySum([1,2,5,2,8,1,5],2) // 10 6 | maxSubarraySum([1,2,5,2,8,1,5],4) // 17 7 | maxSubarraySum([4,2,1,6],1) // 6 8 | maxSubarraySum([4,2,1,6,2],4) // 13 9 | maxSubarraySum([],4) // null 10 | 11 | */ 12 | 13 | function maxSubarraySum(arr, num) { 14 | if (num > arr.length) return null; 15 | 16 | let max = -Infinity; 17 | 18 | for (let i = 0; i < arr.length - num + 1; i++) { 19 | temp = 0; 20 | for (let j = 0; j < num; j++) { 21 | temp += arr[i + j]; 22 | } 23 | if (temp > max) { 24 | max = temp; 25 | } 26 | } 27 | return max; 28 | } 29 | 30 | console.log(maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 2)); //10 31 | console.log(maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 4)); //17 32 | console.log(maxSubarraySum([4, 2, 1, 6], 1)); //6 33 | console.log(maxSubarraySum([4, 2, 1, 6, 2], 4)); //13 34 | console.log(maxSubarraySum([], 4)); //null 35 | -------------------------------------------------------------------------------- /sliding_window/solution_approach.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Write a function called maxSubarraySum which accepts an array of integers and a number called n. The function should calculate the maximum sum of n consecutive elements in the array. 4 | 5 | maxSubarraySum([1,2,5,2,8,1,5],2) // 10 6 | maxSubarraySum([1,2,5,2,8,1,5],4) // 17 7 | maxSubarraySum([4,2,1,6],1) // 6 8 | maxSubarraySum([4,2,1,6,2],4) // 13 9 | maxSubarraySum([],4) // null 10 | 11 | */ 12 | 13 | function maxSubarraySum(arr, num) { 14 | if (num > arr.length) return null; 15 | let maxSum = 0; 16 | let tempSum = 0; 17 | for (let i = 0; i < num; i++) { 18 | maxSum += arr[i]; 19 | console.log(maxSum); 20 | } 21 | tempSum = maxSum; 22 | for (let i = num; i < arr.length; i++) { 23 | tempSum = tempSum - arr[i - num] + arr[i]; 24 | maxSum = Math.max(maxSum, tempSum); 25 | } 26 | return maxSum; 27 | } 28 | 29 | console.log(maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 2)); //10 30 | console.log(maxSubarraySum([1, 2, 5, 2, 8, 1, 5], 4)); //17 31 | console.log(maxSubarraySum([4, 2, 1, 6], 1)); //6 32 | console.log(maxSubarraySum([4, 2, 1, 6, 2], 4)); //13 33 | console.log(maxSubarraySum([], 4)); //null 34 | --------------------------------------------------------------------------------