- Notifications
You must be signed in to change notification settings - Fork5
📚 A list of popular JavaScript algorithms that you'll encounter in the real world. 🧠
License
AllThingsSmitty/javascript-algorithms
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This repository contains a curated list of JavaScript algorithms, organized by category. These range from simple string manipulation to advanced searching and sorting techniques — perfect for interviews and foundational learning.
Note
Popularity is based on common interview topics, educational materials, and developer community usage.
- Prime Number Check
- Fibonacci Sequence (Recursive)
- Factorial of a Number
- Find the GCD (Greatest Common Divisor)
/** * Reverses a string *@param {string} str - The string to reverse *@returns {string} The reversed string */functionreverseString(str){if(typeofstr!=="string")thrownewTypeError("Input must be a string");return[...str].reverse().join("");}console.log(reverseString("hello"));// Output: "olleh"
Explanation: Reverses the characters in a string using the spread operator (modern alternative to split) and reverse. Includes type validation.
/** * Checks if a string is a palindrome (case-insensitive, ignores spaces) *@param {string} str - The string to check *@returns {boolean} True if palindrome, false otherwise */functionisPalindrome(str){if(typeofstr!=="string")thrownewTypeError("Input must be a string");constcleaned=str.toLowerCase().replace(/\s+/g,"");returncleaned===[...cleaned].reverse().join("");}console.log(isPalindrome("racecar"));// Output: trueconsole.log(isPalindrome("A man a plan a canal Panama"));// Output: true
Explanation: Determines if a string reads the same backward as forward. Now handles case-insensitivity and ignores spaces for real-world usage.
/** * Counts the frequency of each character in a string *@param {string} str - The string to analyze *@returns {Object} An object with characters as keys and frequencies as values */functioncharFrequency(str){if(typeofstr!=="string")thrownewTypeError("Input must be a string");return[...str].reduce((freq,char)=>{freq[char]=(freq[char]??0)+1;returnfreq;},{});}console.log(charFrequency("hello"));// Output: { h: 1, e: 1, l: 2, o: 1 }
Explanation: Counts how often each character appears in a string using modernreduce() and nullish coalescing (??). More functional approach.
/** * Determines if two strings are anagrams (ignores case and spaces) *@param {string} str1 - First string *@param {string} str2 - Second string *@returns {boolean} True if anagrams, false otherwise */functionisAnagram(str1,str2){if(typeofstr1!=="string"||typeofstr2!=="string"){thrownewTypeError("Both inputs must be strings");}constnormalize=(str)=>[...str.toLowerCase().replace(/\s+/g,"")].sort().join("");returnnormalize(str1)===normalize(str2);}console.log(isAnagram("listen","silent"));// Output: trueconsole.log(isAnagram("The Eyes","They See"));// Output: true
Explanation: Determines if two strings are anagrams by normalizing case/spaces and comparing sorted characters. Handles real-world edge cases.
/** * Checks if a number is prime *@param {number} num - The number to check *@returns {boolean} True if prime, false otherwise */functionisPrime(num){if(!Number.isInteger(num))thrownewTypeError("Input must be an integer");if(num<=1)returnfalse;if(num<=3)returntrue;if(num%2===0||num%3===0)returnfalse;for(leti=5;i*i<=num;i+=6){if(num%i===0||num%(i+2)===0)returnfalse;}returntrue;}console.log(isPrime(7));// Output: true
Explanation: Checks if a number is prime using an optimized approach with integer validation. Eliminates multiples of 2 and 3 for efficiency.
/** * Generates the nth Fibonacci number using memoization *@param {number} n - The position in Fibonacci sequence *@param {Map} memo - Cache for memoization *@returns {number} The nth Fibonacci number */functionfibonacci(n,memo=newMap()){if(!Number.isInteger(n)||n<0){thrownewTypeError("Input must be a non-negative integer");}if(n<=1)returnn;if(memo.has(n))returnmemo.get(n);constresult=fibonacci(n-1,memo)+fibonacci(n-2,memo);memo.set(n,result);returnresult;}console.log(fibonacci(6));// Output: 8console.log(fibonacci(50));// Output: 12586269025 (efficient with memoization)
Explanation: Generates the nth Fibonacci number recursively with memoization for efficiency. Solves the exponential time complexity problem of naive recursion. Time complexity:O(n) instead ofO(2^n).
/** * Calculates the factorial of a number *@param {number} n - The number to calculate factorial for *@returns {number} The factorial of n */functionfactorial(n){if(!Number.isInteger(n))thrownewTypeError("Input must be an integer");if(n<0)thrownewRangeError("Factorial is not defined for negative numbers");if(n===0||n===1)return1;returnn*factorial(n-1);}console.log(factorial(5));// Output: 120
Explanation: Calculates the factorial of a number recursively with comprehensive input validation using modern type-checking.
/** * Finds the greatest common divisor using Euclidean algorithm *@param {number} a - First number *@param {number} b - Second number *@returns {number} The GCD of a and b */functiongcd(a,b){if(!Number.isInteger(a)||!Number.isInteger(b)){thrownewTypeError("Both inputs must be integers");}a=Math.abs(a);b=Math.abs(b);returnb===0 ?a :gcd(b,a%b);}console.log(gcd(48,18));// Output: 6console.log(gcd(-48,18));// Output: 6
Explanation: Uses the Euclidean algorithm with support for negative numbers and type validation.
/** * Finds two indices in array whose values sum to target *@param {number[]} nums - Array of numbers *@param {number} target - Target sum *@returns {number[]} Array of two indices, or empty array if not found */functiontwoSum(nums,target){if(!Array.isArray(nums)||typeoftarget!=="number"){thrownewTypeError("Input must be an array and a number");}constmap=newMap();for(leti=0;i<nums.length;i++){constcomplement=target-nums[i];if(map.has(complement))return[map.get(complement),i];map.set(nums[i],i);}return[];}console.log(twoSum([2,7,11,15],9));// Output: [0, 1]
Explanation: Finds two indices whose values sum to target using a Map (hash map) for O(n) time complexity. Includes input validation.
/** * Searches for target in a sorted array using binary search *@param {number[]} arr - Sorted array to search in *@param {number} target - Value to search for *@returns {number} Index of target, or -1 if not found */functionbinarySearch(arr,target){if(!Array.isArray(arr)||typeoftarget!=="number"){thrownewTypeError("Input must be an array and a number");}letleft=0,right=arr.length-1;while(left<=right){constmid=left+Math.floor((right-left)/2);if(arr[mid]===target)returnmid;if(arr[mid]<target)left=mid+1;elseright=mid-1;}return-1;}console.log(binarySearch([1,2,3,4,5],4));// Output: 3
Explanation: Searches for target in sorted array using divide-and-conquer. Usesleft + Math.floor((right - left) / 2) to avoid overflow issues.
/** * Sorts an array using bubble sort algorithm *@param {number[]} arr - Array to sort *@returns {number[]} Sorted array */functionbubbleSort(arr){if(!Array.isArray(arr))thrownewTypeError("Input must be an array");constsorted=[...arr];// Create copy to avoid mutating originalfor(leti=0;i<sorted.length;i++){for(letj=0;j<sorted.length-i-1;j++){if(sorted[j]>sorted[j+1]){[sorted[j],sorted[j+1]]=[sorted[j+1],sorted[j]];}}}returnsorted;}console.log(bubbleSort([5,3,8,4,2]));// Output: [2, 3, 4, 5, 8]
Explanation: Sorts an array by repeatedly swapping adjacent elements. Modern version uses array spread to avoid mutating the original array.
/** * Sorts an array using quick sort algorithm *@param {number[]} arr - Array to sort *@returns {number[]} Sorted array */functionquickSort(arr){if(!Array.isArray(arr))thrownewTypeError("Input must be an array");if(arr.length<=1)returnarr;constpivot=arr[Math.floor(arr.length/2)];constleft=arr.filter((x)=>x<pivot);constmiddle=arr.filter((x)=>x===pivot);constright=arr.filter((x)=>x>pivot);return[...quickSort(left), ...middle, ...quickSort(right)];}console.log(quickSort([3,6,8,10,1,2,1]));// Output: [1, 1, 2, 3, 6, 8, 10]
Explanation: A divide-and-conquer sorting algorithm withO(n log n) average-case complexity. Uses middle pivot to handle duplicates better, and maintains immutability.
/** * Merges two sorted arrays into one sorted array *@param {number[]} arr1 - First sorted array *@param {number[]} arr2 - Second sorted array *@returns {number[]} Merged sorted array */functionmergeSortedArrays(arr1,arr2){if(!Array.isArray(arr1)||!Array.isArray(arr2)){thrownewTypeError("Both inputs must be arrays");}constmerged=[];leti=0,j=0;while(i<arr1.length&&j<arr2.length){if(arr1[i]<arr2[j]){merged.push(arr1[i++]);}else{merged.push(arr2[j++]);}}return[...merged, ...arr1.slice(i), ...arr2.slice(j)];}console.log(mergeSortedArrays([1,3,5],[2,4,6]));// Output: [1, 2, 3, 4, 5, 6]
Explanation: Merges two sorted arrays efficiently in O(n + m) time. Modern syntax with spread operator.
/** * Finds the maximum value in an array *@param {number[]} arr - Array to search *@returns {number} The maximum value */functionfindMax(arr){if(!Array.isArray(arr)||arr.length===0){thrownewTypeError("Input must be a non-empty array");}returnMath.max(...arr);}// Alternative for very large arrays (avoids stack overflow):functionfindMaxAlternative(arr){if(!Array.isArray(arr)||arr.length===0){thrownewTypeError("Input must be a non-empty array");}returnarr.reduce((max,current)=>(current>max ?current :max));}console.log(findMax([1,2,3,4,5]));// Output: 5
Explanation: Finds the largest number. Now includes validation and an alternative usingreduce() for very large arrays to avoid stack overflow from spread operator.
/** * Creates a debounced function that delays execution *@param {Function} fn - Function to debounce *@param {number} delay - Delay in milliseconds *@returns {Function} Debounced function */functiondebounce(fn,delay){if(typeoffn!=="function"||typeofdelay!=="number"){thrownewTypeError("First argument must be a function, second a number");}lettimerId;returnfunction(...args){clearTimeout(timerId);timerId=setTimeout(()=>fn.apply(this,args),delay);};}// Modern async version with promisesasyncfunctiondebounceAsync(fn,delay){if(typeoffn!=="function"||typeofdelay!=="number"){thrownewTypeError("First argument must be a function, second a number");}lettimerId;returnfunction(...args){returnnewPromise((resolve)=>{clearTimeout(timerId);timerId=setTimeout(()=>{resolve(fn.apply(this,args));},delay);});};}constlog=debounce(()=>console.log("Debounced!"),300);log();log();log();// Logs once after 300ms of inactivity
Explanation: Limits rate at which a function fires. Classic callback version and modern async/Promise version for modern use cases. Includes parameter validation.
About
📚 A list of popular JavaScript algorithms that you'll encounter in the real world. 🧠
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.