├── 2dArray ├── Multiplication.java ├── Searching.java └── Transpose.java ├── Arrays ├── BestTimeToBuyAndSellStock.java ├── BestTimeToBuyAndSellStock.js ├── Boyer-MooreVotingAlgorithm.js ├── ContainerWithMostWater.js ├── ContainsDuplicate.java ├── ContainsDuplicate.js ├── FindAllNumbersDisappearedInAnArray.java ├── FindAllNumbersDisappearedInAnArray.js ├── FindLongestSubstring.js ├── IntersectionOfTwoArrays.java ├── IntersectionOfTwoArrays.js ├── IntersectionOfTwoArraysII.java ├── IntersectionOfTwoArraysII.js ├── KadanesAlgorithm.js ├── LongestContinuousIncreasingSubsequence.js ├── MaximumAscendingSubarraySum.java ├── MaximumAscendingSubarraySum.js ├── MergeSortedArray.js ├── MinSubArrayLen.js ├── MissingNumber.java ├── MissingNumber.js ├── MoveZeros.java ├── MoveZeros.js ├── PlusOne.java ├── PlusOne.js ├── README.md ├── RemoveDupicatesFromSortedArray.java ├── RemoveDupicatesFromSortedArray.js ├── RemoveElement.java ├── RemoveElement.js ├── ReverseAnArray.js ├── RomanToInteger.java ├── RomanToInteger.js ├── RotateLeft.js ├── SubarrayWithGivenSum.java ├── SummaryRanges.js ├── ThirdMaximumNumber.js ├── TwoSum.js └── TwoSumSorted.js ├── BasicProblems ├── BenjaminBulbs.js ├── CountDigits.js ├── Gcd&Lcm.js ├── InverseOfANumber.js ├── PrimeFactors.js ├── PrimeNo.js ├── PrintDigits.js ├── PrintFibonacci.js ├── PythagoreanTriplet.js ├── README.md ├── ReverseANumber.js ├── RotateANumber.js └── SieveOfEratosthenes.js ├── Bit Manipulation ├── Basics.js ├── DivisibleBy2.js ├── FindUnique.java ├── FindUnique.js ├── MissingNumber.js ├── NoOf1s.js ├── README.md └── SubSet.js ├── Data Structures ├── Java │ └── README.md └── JavaScript │ ├── BST.js │ ├── DoublyLinkedList.js │ ├── Queue.js │ ├── README.md │ ├── SinglyLinkedList.js │ ├── Stack.js │ ├── package-lock.json │ ├── package.json │ ├── tests │ ├── BST.test.js │ ├── DoublyLinkedList.test.js │ ├── Queue.test.js │ ├── SinglyLinkedList.test.js │ └── Stack.test.js │ └── yarn.lock ├── Disjoint Sets ├── QuickFind.js ├── QuickUnion.js ├── QuickUnionWithPathCompression.js └── WeightedQuickUnion.js ├── LinkedList ├── DeleteNodeInALinkedList.java ├── DeleteNodeInALinkedList.js ├── MergeTwoSortedLists.java ├── MergeTwoSortedLists.js └── PalindromeLinkedList.js ├── Miscellaneous ├── HigherOrderMethods.js ├── Polyfills.js └── Utils.js ├── Pattern Problems ├── Chessboard.js └── Triangle.js ├── README.md ├── Recursion ├── CapitalizeFirst.js ├── CollectStrings.js ├── EvenOdd.js ├── FlattenNestedArrays.js ├── NestedEvenSum.js ├── README.md ├── SomeRecursive.js └── StringifyNumbers.js ├── Searching ├── BinarySearch.js ├── FindSmallestLetterGreaterThanTarget.js ├── FirstBadVersion.java ├── FirstBadVersion.js ├── IntersectionOfTwoArrays.java ├── IntersectionOfTwoArrays.js ├── LinearSearch.js ├── PeakIndexInAMountainArray.js ├── README.md ├── SearchInsertPosition.java └── SearchInsertPosition.js ├── Sliding Window ├── FindAllAnagramsInAString.java ├── FindAllAnagramsInAString.js ├── FruitIntoBaskets.java ├── FruitIntoBaskets.js ├── LongestSubstringWithoutRepeatingCharacters.java ├── LongestSubstringWithoutRepeatingCharacters.js ├── MaxConsecutiveOnesIII.java ├── MaxConsecutiveOnesIII.js ├── MinimumWindowSubstring.java └── MinimumWindowSubstring.js ├── Sorting ├── BubbleSort.js ├── InsertionSort.js ├── MergeSort.js ├── QuickSort.js ├── README.md ├── RadixSort.js └── SelectionSort.js ├── StacksNQueues ├── BackspaceStringCompare.java ├── BackspaceStringCompare.js ├── ValidParentheses.java └── ValidParentheses.js ├── Strings ├── LowerUpper.js └── MaxFreq.js └── TwoPointers ├── BackspaceStringCompare.java ├── BackspaceStringCompare.js ├── FruitIntoBaskets.java ├── FruitIntoBaskets.js ├── IntersectionOfTwoArrays.java ├── IntersectionOfTwoArrays.js ├── LongPressedName.java ├── LongPressedName.js ├── MaxConsecutiveOnesIII.java ├── MaxConsecutiveOnesIII.js └── TwoSumSorted.js /2dArray/Multiplication.java: -------------------------------------------------------------------------------- 1 | // int[][] arr1 = new int[n1][n2]; 2 | // int[][] arr2 = new int[n2][n3]; 3 | // int[][] ans = new int[n1][n3]; 4 | 5 | // Time Complexity O(n^3) 6 | // Space Complexity O(1) 7 | 8 | public static int[][] multiplication(int[][] arr1, int[][] arr2, int n1, int n2, int n3){ 9 | int[][] ans; 10 | for(int i = 0; i < n1; i++){ 11 | for(int j = 0; j < n3; j++){ 12 | for(int k = 0; k < n2; k++){ 13 | ans[i][j] += arr1[i][k] * arr2[k][j]; 14 | } 15 | } 16 | } 17 | return ans; 18 | } 19 | -------------------------------------------------------------------------------- /2dArray/Searching.java: -------------------------------------------------------------------------------- 1 | // Searching an element in a sorted 2d array 2 | // We start from top right corner or bottom left corner (from other two corners elements only increase or decrease) 3 | // If the element is greater than the key we reduce the column and if it is lesser than the key we increment the row 4 | 5 | // Time Complexity O(n) 6 | // Space Complexity O(1) 7 | 8 | public static void search(int[][] arr,int key, int row, int column){ 9 | int r = 0; // row 10 | int c = column - 1; // column 11 | boolean flag = false; 12 | 13 | while(r < row && c > 0){ 14 | if(key == arr[r][c]){ 15 | System.out.println("Element Found"); 16 | flag = true; 17 | break; 18 | }else{ 19 | if(arr[r][c] > key) 20 | c--; 21 | else 22 | r++; 23 | } 24 | } 25 | if(!flag) 26 | System.out.println("Element not Found"); 27 | } 28 | -------------------------------------------------------------------------------- /2dArray/Transpose.java: -------------------------------------------------------------------------------- 1 | // Time Complexity O(n^2) 2 | // Space Complexity O(1) 3 | 4 | public static void transpose(int[][] arr, int row, int column){ 5 | for(int i = 0; i < row; i++){ 6 | for(int j = i; j < column; j++){ 7 | int temp = arr[i][j]; 8 | arr[i][j] = arr[j][i]; 9 | arr[j][i] = temp; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Arrays/BestTimeToBuyAndSellStock.java: -------------------------------------------------------------------------------- 1 | // 121. Best Time to Buy and Sell Stock 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public static int maxProfit(int[] prices) { 7 | int minPrice = prices[0]; 8 | int maxProfit = 0; 9 | for (int i = 1; i < prices.length; i++) { 10 | if (prices[i] <= minPrice) { 11 | minPrice = prices[i]; 12 | } else { 13 | int newProfit = prices[i] - minPrice; 14 | if (newProfit > maxProfit) { 15 | maxProfit = newProfit; 16 | } 17 | } 18 | } 19 | return maxProfit; 20 | } 21 | -------------------------------------------------------------------------------- /Arrays/BestTimeToBuyAndSellStock.js: -------------------------------------------------------------------------------- 1 | // 121. Best Time to Buy and Sell Stock 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var maxProfit = function (prices) { 7 | let minPrice = prices[0]; 8 | let maxProfit = 0; 9 | for (let i = 1; i < prices.length; i++) { 10 | if (prices[i] <= minPrice) { 11 | minPrice = prices[i]; 12 | } else { 13 | const newProfit = prices[i] - minPrice; 14 | if (newProfit > maxProfit) { 15 | maxProfit = newProfit; 16 | } 17 | } 18 | } 19 | return maxProfit; 20 | }; 21 | -------------------------------------------------------------------------------- /Arrays/Boyer-MooreVotingAlgorithm.js: -------------------------------------------------------------------------------- 1 | // This algorithm can be used to find a element that appears more than floor(n/2) times in an array 2 | // Because the majority element appears more than n/2 times in the array i.e a minimum of floor(n/2) + 1 times out of n 3 | // Therefore even if all the minority elements cancel out the majority elements one instance of majority element will be left in case of odd no of elements 4 | // and minimum two instances will be left in case of even no of elements 5 | 6 | // 169. Majority Element 7 | 8 | // Time Complexity O(n) 9 | // Space Complexity O(1) 10 | 11 | var majorityElement = function (nums) { 12 | let count = 0; 13 | let maxElement = nums[0]; 14 | for (let i = 0; i < nums.length; i++) { 15 | if (count == 0) maxElement = nums[i]; 16 | if (maxElement == nums[i]) count++; 17 | else count--; 18 | } 19 | return maxElement; 20 | }; 21 | -------------------------------------------------------------------------------- /Arrays/ContainerWithMostWater.js: -------------------------------------------------------------------------------- 1 | // Time Complexity O(n) 2 | // Space Complexity O(1) 3 | 4 | var maxArea = function(height) { 5 | let length = height.length - 1; 6 | let leftPtr = 0; 7 | let rightPtr = height.length - 1; 8 | let maxArea = 0; 9 | 10 | while (leftPtr < rightPtr){ 11 | const area = length * Math.min(height[leftPtr], height[rightPtr]); 12 | maxArea = Math.max(maxArea, area); 13 | 14 | length--; 15 | if (height[leftPtr] <= height[rightPtr]) 16 | leftPtr++; 17 | else 18 | rightPtr--; 19 | } 20 | 21 | return maxArea; 22 | }; 23 | -------------------------------------------------------------------------------- /Arrays/ContainsDuplicate.java: -------------------------------------------------------------------------------- 1 | // Return true if the array contains duplicates return false if it doesn't 2 | // 217. Contains Duplicate 3 | 4 | // Time Complexity O(n) 5 | // Space Complexity O(n) 6 | 7 | public boolean containsDuplicate(int[] nums) { 8 | HashSet set = new HashSet<>(); 9 | for (int i = 0; i < nums.length; i++) { 10 | if (set.contains(nums[i])) { 11 | return true; 12 | } else { 13 | set.add(nums[i]); 14 | } 15 | } 16 | return false; 17 | } 18 | -------------------------------------------------------------------------------- /Arrays/ContainsDuplicate.js: -------------------------------------------------------------------------------- 1 | // Return true if the array contains duplicates return false if it doesn't 2 | // 217. Contains Duplicate 3 | 4 | // Time Complexity O(n) 5 | // Space Complexity O(n) 6 | 7 | var containsDuplicate = function(nums) { 8 | const map = new Map(); 9 | for (let i = 0; i < nums.length; i++) { 10 | if (map.has(nums[i])) { 11 | return true; 12 | } else { 13 | map.set(nums[i], 1); 14 | } 15 | } 16 | return false; 17 | }; 18 | -------------------------------------------------------------------------------- /Arrays/FindAllNumbersDisappearedInAnArray.java: -------------------------------------------------------------------------------- 1 | // 448. Find All Numbers Disappeared in an Array 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public List findDisappearedNumbers(int[] nums) { 7 | ArrayList result = new ArrayList(); 8 | for (int i = 0; i < nums.length; i++) { 9 | int temp = Math.abs(nums[i]) - 1; 10 | if (nums[temp] > 0) { 11 | nums[temp] = -1 * nums[temp]; 12 | } 13 | } 14 | for (int i = 0; i < nums.length; i++) { 15 | if (nums[i] > 0) { 16 | result.add(i + 1); 17 | } 18 | } 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /Arrays/FindAllNumbersDisappearedInAnArray.js: -------------------------------------------------------------------------------- 1 | // 448. Find All Numbers Disappeared in an Array 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var findDisappearedNumbers = function(nums) { 7 | const ans = []; 8 | for (let i = 0; i < nums.length; i++) { 9 | let temp = Math.abs(nums[i]) - 1; 10 | if (nums[temp] > 0) { 11 | nums[temp] = -1 * nums[temp]; 12 | } 13 | } 14 | for (let i = 0; i < nums.length; i++) { 15 | if (nums[i] > 0) ans.push(i + 1); 16 | } 17 | return ans; 18 | }; 19 | -------------------------------------------------------------------------------- /Arrays/FindLongestSubstring.js: -------------------------------------------------------------------------------- 1 | // write a function that returns the length of longest substring with all distinct characters 2 | // findLongestSubstring('') // 0 3 | // findLongestSubstring('rithmschool') // 7 4 | // findLongestSubstring('thisisawesome') // 6 5 | // findLongestSubstring('thecatinthehat') // 7 6 | // findLongestSubstring('bbbbbb') // 1 7 | // findLongestSubstring('longestsubstring') // 8 8 | // findLongestSubstring('thisishowwedoit') // 6 9 | 10 | function findLongestSubstring(str) { 11 | let maxLen = 0; 12 | let start = 0; 13 | let end = 1; 14 | const map = new Map(); 15 | map.set(str[0], 0); 16 | 17 | while (end < str.length) { 18 | if (map.has(str[end]) && map.get(str[end]) >= start) { 19 | start = map.get(str[end]) + 1; 20 | map.set(str[end], end); 21 | } else { 22 | map.set(str[end], end); 23 | } 24 | if (end - start + 1 > maxLen) { 25 | maxLen = end - start + 1; 26 | } 27 | end++; 28 | } 29 | 30 | return maxLen; 31 | } 32 | -------------------------------------------------------------------------------- /Arrays/IntersectionOfTwoArrays.java: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // Solution 1: Using a hash map 4 | // Time Complexity: O(n) 5 | // Space Complexity: O(n) 6 | 7 | public int[] intersection(int[] nums1, int[] nums2) { 8 | HashSet map = new HashSet<>(); 9 | ArrayList list = new ArrayList<>(); 10 | for (int num : nums1) { 11 | if (!map.contains(num)) { 12 | map.add(num); 13 | } 14 | } 15 | for (int num : nums2) { 16 | if (map.contains(num)) { 17 | list.add(num); 18 | map.remove(num); 19 | } 20 | } 21 | 22 | int[] output = new int[list.size()]; 23 | for (int i = 0; i < list.size(); i++) { 24 | output[i] = list.get(i); 25 | } 26 | return output; 27 | } 28 | 29 | // Solution 2: in search folder 30 | // Solution 3: in 2 pointer folder 31 | -------------------------------------------------------------------------------- /Arrays/IntersectionOfTwoArrays.js: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // Solution 1: Using a hash map 4 | // Time Complexity: O(n) 5 | // Space Complexity: O(n) 6 | 7 | var intersection = function (nums1, nums2) { 8 | const map = new Map(); 9 | const output = []; 10 | for (const num of nums1) { 11 | if (!map.has(num)) { 12 | map.set(num, 1); 13 | } 14 | } 15 | for (const num of nums2) { 16 | if (map.has(num)) { 17 | output.push(num); 18 | map.delete(num); 19 | } 20 | } 21 | return output; 22 | }; 23 | 24 | // Solution 2: in search folder 25 | // Solution 3: in 2 pointer folder 26 | -------------------------------------------------------------------------------- /Arrays/IntersectionOfTwoArraysII.java: -------------------------------------------------------------------------------- 1 | // 350. Intersection of Two Arrays II 2 | 3 | // Time Complexity O(n + m) 4 | // Space Complexity O(n) 5 | 6 | class Solution { 7 | public int[] intersect(int[] nums1, int[] nums2) { 8 | HashMap map = new HashMap<>(); 9 | ArrayList intersection = new ArrayList(); 10 | 11 | for (int element: nums1) { 12 | if (map.containsKey(element)) { 13 | map.replace(element, map.get(element) + 1); 14 | } else { 15 | map.put(element, 1); 16 | } 17 | } 18 | 19 | for (int element : nums2) { 20 | if (map.containsKey(element) && map.get(element) != 0) { 21 | map.replace(element, map.get(element) - 1); 22 | intersection.add(element); 23 | } 24 | } 25 | 26 | int[] result = new int[intersection.size()]; 27 | for (int i = 0; i < intersection.size(); i++) { 28 | result[i] = intersection.get(i); 29 | } 30 | return result; 31 | } 32 | } 33 | 34 | // If arrays are sorted we can use 2 pointers to build the result array O(n + m), O(1) 35 | // If arrays are sorted and one is larger than the other we can use binary serach O(nlogm), O(1) 36 | -------------------------------------------------------------------------------- /Arrays/IntersectionOfTwoArraysII.js: -------------------------------------------------------------------------------- 1 | // 350. Intersection of Two Arrays II 2 | 3 | // Time Complexity O(n + m) 4 | // Space Complexity O(n) 5 | 6 | var intersect = function (nums1, nums2) { 7 | const map = new Map(); 8 | const result = []; 9 | 10 | for (const element of nums1) { 11 | if (map.has(element)) { 12 | map.set(element, map.get(element) + 1); 13 | } else { 14 | map.set(element, 1); 15 | } 16 | } 17 | 18 | for (const element of nums2) { 19 | if (map.get(element)) { 20 | map.set(element, map.get(element) - 1); 21 | result.push(element); 22 | } 23 | } 24 | 25 | return result; 26 | }; 27 | 28 | // If arrays are sorted we can use 2 pointers to build the result array O(n + m), O(1) 29 | // If arrays are sorted and one is larger than the other we can use binary serach O(nlogm), O(1) 30 | -------------------------------------------------------------------------------- /Arrays/KadanesAlgorithm.js: -------------------------------------------------------------------------------- 1 | // Kadane's algorithm - used to find the maximum subarray sum 2 | // at every iteration we choose the greater number between arr[i] and currentSum + arr[i] 3 | // from the above statement we can conclude that whenever the currentSum becomes -ve we'll reset the currentSum 4 | // because arr[i] will always be greater than currentSum + arr[i] if currentSum is negative 5 | 6 | // Time Complexity O(n) 7 | // Space Complexity O(1) 8 | 9 | function kadanes(arr) { 10 | let currentSum = 0; 11 | let maxSum = Number.MIN_VALUE; 12 | for (let i = 0; i < arr.length; i++) { 13 | if (currentSum < 0) 14 | currentSum = 0; 15 | currentSum += arr[i]; 16 | if (currentSum > maxSum) 17 | maxSum = currentSum; 18 | } 19 | return maxSum; 20 | } 21 | -------------------------------------------------------------------------------- /Arrays/LongestContinuousIncreasingSubsequence.js: -------------------------------------------------------------------------------- 1 | // 674. Longest Continuous Increasing Subsequence 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var findLengthOfLCIS = function(nums) { 7 | if (!nums.length) return 0; 8 | let count = 1; 9 | let maxCount = 1; 10 | for (let i = 0; i < nums.length - 1; i++) { 11 | if (nums[i + 1] > nums[i]) { 12 | count++; 13 | maxCount = count > maxCount ? count : maxCount; 14 | } else count = 1; 15 | } 16 | return maxCount; 17 | }; 18 | -------------------------------------------------------------------------------- /Arrays/MaximumAscendingSubarraySum.java: -------------------------------------------------------------------------------- 1 | // 1800. Maximum Ascending Subarray Sum 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public int maxAscendingSum(int[] nums) { 7 | int maxSum = nums[0]; 8 | int currentSum = nums[0]; 9 | int ptr = 1; 10 | 11 | while (ptr < nums.length) { 12 | if (nums[ptr - 1] < nums[ptr]) { 13 | currentSum += nums[ptr]; 14 | if (currentSum > maxSum) { 15 | maxSum = currentSum; 16 | } 17 | } else { 18 | currentSum = nums[ptr]; 19 | } 20 | ptr++; 21 | } 22 | 23 | return maxSum; 24 | } 25 | -------------------------------------------------------------------------------- /Arrays/MaximumAscendingSubarraySum.js: -------------------------------------------------------------------------------- 1 | // 1800. Maximum Ascending Subarray Sum 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var maxAscendingSum = function(nums) { 7 | let maxSum = nums[0]; 8 | let currentSum = nums[0]; 9 | let ptr = 1; 10 | 11 | while (ptr < nums.length) { 12 | if (nums[ptr - 1] < nums[ptr]) { 13 | currentSum += nums[ptr]; 14 | if (currentSum > maxSum) { 15 | maxSum = currentSum; 16 | } 17 | } else { 18 | currentSum = nums[ptr] 19 | } 20 | ptr++; 21 | } 22 | 23 | return maxSum; 24 | }; 25 | -------------------------------------------------------------------------------- /Arrays/MergeSortedArray.js: -------------------------------------------------------------------------------- 1 | // 88. Merge Sorted Array 2 | 3 | // Time Complexity O(m + n) 4 | // Space Complexity O(m + n) 5 | 6 | // optimal solution T: O(m + n) S: O(1) 7 | 8 | var merge = function(nums1, m, nums2, n) { 9 | let ans = []; 10 | let ansLen = 0; 11 | let i = 0; 12 | let j = 0; 13 | while (i < m && j < n) { 14 | if (nums1[i] <= nums2[j]) 15 | ans[ansLen++] = nums1[i++]; 16 | else 17 | ans[ansLen++] = nums2[j++]; 18 | } 19 | if (i < m) 20 | for (let k = i; k < m; k++) 21 | ans[ansLen++] = nums1[k]; 22 | if (j < n) 23 | for (let k = j; k < n; k++) 24 | ans[ansLen++] = nums2[k]; 25 | for (let k = 0; k < ans.length; k++) 26 | nums1[k] = ans[k]; 27 | }; 28 | -------------------------------------------------------------------------------- /Arrays/MinSubArrayLen.js: -------------------------------------------------------------------------------- 1 | // function takes two arguments one is an array of +ve integers second is a +ve integer 2 | // function should return min length of the contiguous sub array of which the sum is greater than or equal to the second argument 3 | // return 0 if no such such sub array exists 4 | 5 | // minSubArrayLen([2,3,1,2,4,3], 7) // 2 -> because [4,3] is the smallest subarray 6 | // minSubArrayLen([2,1,6,5,4], 9) // 2 -> because [5,4] is the smallest subarray 7 | // minSubArrayLen([3,1,7,11,2,9,8,21,62,33,19], 52) // 1 -> because [62] is greater than 52 8 | // minSubArrayLen([1,4,16,22,5,7,8,9,10],39) // 3 9 | // minSubArrayLen([1,4,16,22,5,7,8,9,10],55) // 5 10 | // minSubArrayLen([4, 3, 3, 8, 1, 2, 3], 11) // 2 11 | // minSubArrayLen([1,4,16,22,5,7,8,9,10],95) // 0 12 | 13 | function minSubArrayLen(arr, minSum) { 14 | let start = 0; 15 | let end = 1; 16 | let minLen = Number.MAX_SAFE_INTEGER; 17 | let sum = arr[start] + arr[end]; 18 | 19 | while (end < arr.length) { 20 | if (sum >= minSum) { 21 | if (end - start + 1 < minLen) { 22 | minLen = end - start + 1; 23 | } 24 | sum -= arr[start++]; 25 | } else { 26 | sum += arr[++end]; 27 | } 28 | } 29 | 30 | return minLen === Number.MAX_SAFE_INTEGER ? 0 : minLen; 31 | } 32 | -------------------------------------------------------------------------------- /Arrays/MissingNumber.java: -------------------------------------------------------------------------------- 1 | // Find the missing number from the range 0 to n 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public int missingNumber(int[] nums) { 7 | int expectedSum = (nums.length * (nums.length + 1)) / 2; 8 | int sum = 0; 9 | for(int i = 0; i < nums.length; i++){ 10 | sum += nums[i]; 11 | } 12 | return expectedSum - sum; 13 | } 14 | 15 | // bit manipulation 16 | 17 | public int missingNumber(int[] nums) { 18 | int ans = 0; 19 | for(int i = 0; i < nums.length; i++){ 20 | ans ^= nums[i]; 21 | } 22 | for(int i = 0; i <= nums.length; i++){ 23 | ans ^= i; 24 | } 25 | return ans; 26 | } 27 | -------------------------------------------------------------------------------- /Arrays/MissingNumber.js: -------------------------------------------------------------------------------- 1 | // Find the missing number from the range 0 to n 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var missingNumber = function(nums) { 7 | const expectedSum = (nums.length * (nums.length + 1)) / 2; 8 | const sum = nums.reduce((accum, num) => accum + num, 0); 9 | return expectedSum - sum; 10 | }; 11 | 12 | // bit manipulation 13 | var missingNumber = function(nums) { 14 | let ans; 15 | for(let i = 0; i < nums.length; i++){ 16 | ans ^= nums[i]; 17 | } 18 | for(let i = 0; i <= nums.length; i++){ 19 | ans ^= i; 20 | } 21 | return ans 22 | }; 23 | -------------------------------------------------------------------------------- /Arrays/MoveZeros.java: -------------------------------------------------------------------------------- 1 | // 283. Move Zeroes 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | class Solution { 7 | public void moveZeroes(int[] nums) { 8 | int zeroCount = 0; 9 | int slowPtr = 0; 10 | for (int fastPtr: nums) { 11 | if (fastPtr != 0) { 12 | nums[slowPtr++] = fastPtr; 13 | } else { 14 | zeroCount++; 15 | } 16 | } 17 | for (int i = nums.length - 1; zeroCount > 0; i--, zeroCount--) { 18 | nums[i] = 0; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Arrays/MoveZeros.js: -------------------------------------------------------------------------------- 1 | // 283. Move Zeroes 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var moveZeroes = function(nums) { 7 | let zeroCount = 0; 8 | let slowPtr = 0; 9 | for (let elem of nums) { 10 | if (elem !== 0) { 11 | nums[slowPtr++] = elem; 12 | } else { 13 | zeroCount++; 14 | } 15 | } 16 | for (let i = nums.length - 1; zeroCount > 0; i--, zeroCount--) { 17 | nums[i] = 0; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Arrays/PlusOne.java: -------------------------------------------------------------------------------- 1 | // 66. Plus One 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) / O(n) 5 | 6 | class Solution { 7 | public int[] plusOne(int[] digits) { 8 | int power = digits.length - 1; 9 | while (power >= 0) { 10 | if (digits[power] == 9) { 11 | if (power == 0) { 12 | digits[power] = 0; 13 | int[] newArray = new int[digits.length + 1]; 14 | newArray[0] = 1; 15 | for (int i = 0; i < digits.length; i++) { 16 | newArray[i+1] = digits[i]; 17 | } 18 | return newArray; 19 | } else { 20 | digits[power] = 0; 21 | } 22 | power--; 23 | } else { 24 | digits[power]++; 25 | return digits; 26 | } 27 | } 28 | 29 | return digits; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Arrays/PlusOne.js: -------------------------------------------------------------------------------- 1 | // 66. Plus One 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) / O(n) 5 | 6 | var plusOne = function (digits) { 7 | let power = digits.length - 1; 8 | while (power >= 0) { 9 | if (digits[power] === 9) { 10 | if (power === 0) { 11 | digits[power] = 0; 12 | digits.unshift(1); 13 | } else { 14 | digits[power] = 0; 15 | } 16 | power--; 17 | } else { 18 | digits[power]++; 19 | return digits; 20 | } 21 | } 22 | 23 | return digits; 24 | }; 25 | -------------------------------------------------------------------------------- /Arrays/README.md: -------------------------------------------------------------------------------- 1 | ### Good Problems 2 | - [Find All Numbers Disappeared In An Array](https://github.com/RohitDhatrak/DS-Algo/blob/main/Arrays/FindAllNumbersDisappearedInAnArray.js) 3 | - [Valid Parentheses](https://github.com/RohitDhatrak/DS-Algo/blob/main/Arrays/ValidParentheses.js) 4 | 5 | ### Algorithms 6 | - [Kadanes Algorithm](https://github.com/RohitDhatrak/DS-Algo/blob/main/Arrays/KadanesAlgorithm.js) 7 | - [Boyer-Moore Voting Algorithm](https://github.com/RohitDhatrak/DS-Algo/blob/main/Arrays/Boyer-MooreVotingAlgorithm.js) 8 | -------------------------------------------------------------------------------- /Arrays/RemoveDupicatesFromSortedArray.java: -------------------------------------------------------------------------------- 1 | // Leetcode - 26. Remove Duplicates from Sorted Array 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public static int removeDuplicates(int[] nums) { 7 | if (nums.length == 0) return 0; 8 | int lastPos = 0; 9 | for (int i = 1; i < nums.length; i++) { 10 | if (nums[i] > nums[lastPos]) { 11 | nums[++lastPos] = nums[i]; 12 | } 13 | } 14 | return lastPos + 1; 15 | } 16 | -------------------------------------------------------------------------------- /Arrays/RemoveDupicatesFromSortedArray.js: -------------------------------------------------------------------------------- 1 | // Leetcode - 26. Remove Duplicates from Sorted Array 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var removeDuplicates = function(nums) { 7 | if (!nums.length) return 0; 8 | let lastPos = 0; 9 | for (let i = 1; i < nums.length; i++) { 10 | if (nums[i] > nums[lastPos]) { 11 | nums[++lastPos] = nums[i]; 12 | } 13 | } 14 | return lastPos + 1; 15 | }; 16 | -------------------------------------------------------------------------------- /Arrays/RemoveElement.java: -------------------------------------------------------------------------------- 1 | // Leetcode - 27. Remove Element 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public static int removeElement(int[] nums, int val) { 7 | int j = 0; 8 | for (int i = 0; i < nums.length; i++) { 9 | if (nums[j] == val && nums[i] != val) { 10 | int temp = nums[j]; 11 | nums[j] = nums[i]; 12 | nums[i] = temp; 13 | } 14 | if (nums[j] != val) { 15 | j++; 16 | } 17 | } 18 | return j; 19 | } 20 | -------------------------------------------------------------------------------- /Arrays/RemoveElement.js: -------------------------------------------------------------------------------- 1 | // Leetcode - 27. Remove Element 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var removeElement = function(nums, val) { 7 | let j = 0; 8 | for (let i = 0; i < nums.length; i++) { 9 | if (nums[j] == val && nums[i] != val) { 10 | const temp = nums[j]; 11 | nums[j] = nums[i]; 12 | nums[i] = temp; 13 | } 14 | if (nums[j] != val) { 15 | j++; 16 | } 17 | } 18 | return j; 19 | }; 20 | -------------------------------------------------------------------------------- /Arrays/ReverseAnArray.js: -------------------------------------------------------------------------------- 1 | // We use two pointers and keep swapping the elements 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | function reverseArray(arr) { 7 | for (let i = 0, j = arr.length - 1; i < j; i++, j--) { 8 | let temp = arr[i]; 9 | arr[i] = arr[j]; 10 | arr[j] = temp; 11 | } 12 | return arr; 13 | } 14 | -------------------------------------------------------------------------------- /Arrays/RomanToInteger.java: -------------------------------------------------------------------------------- 1 | // 13. Roman to Integer 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public static int romanToInt(String s) { 7 | int total = 0; 8 | for (int i = 0; i < s.length(); i++) { 9 | char currentNum = s.charAt(i); 10 | int value = getIntVal(currentNum); 11 | if (i < s.length() - 1) { 12 | char nextNum = s.charAt(i + 1); 13 | if (getIntVal(currentNum) < getIntVal(nextNum)) { 14 | value = getIntVal(nextNum) - getIntVal(currentNum); 15 | i++; 16 | } 17 | } 18 | total += value; 19 | } 20 | return total; 21 | } 22 | 23 | public static int getIntVal(char c){ 24 | switch(c){ 25 | case 'I': 26 | return 1; 27 | case 'V': 28 | return 5; 29 | case 'X': 30 | return 10; 31 | case 'L': 32 | return 50; 33 | case 'C': 34 | return 100; 35 | case 'D': 36 | return 500; 37 | case 'M': 38 | return 1000; 39 | default: 40 | return 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Arrays/RomanToInteger.js: -------------------------------------------------------------------------------- 1 | // 13. Roman to Integer 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var romanToInt = function (s) { 7 | const roman = { 8 | I: 1, 9 | V: 5, 10 | X: 10, 11 | L: 50, 12 | C: 100, 13 | D: 500, 14 | M: 1000, 15 | }; 16 | 17 | let total = 0; 18 | for (let i = 0; i < s.length; i++) { 19 | let value = roman[s[i]]; 20 | if (roman[s[i]] < roman[s[i + 1]]) { 21 | value = roman[s[i + 1]] - roman[s[i]]; 22 | i++; 23 | } 24 | total += value; 25 | } 26 | return total; 27 | }; 28 | -------------------------------------------------------------------------------- /Arrays/RotateLeft.js: -------------------------------------------------------------------------------- 1 | // Rotate an array left d times 2 | 3 | // Time Complexity O(d * n) 4 | // Space Complexity O(1) 5 | function rotateLeft(d, arr) { 6 | d %= arr.length; 7 | for (let i = 0; i < d; i++){ 8 | let temp = arr[0]; 9 | for (let j = 0; j < arr.length - 1; j++){ 10 | arr[j] = arr[j + 1]; 11 | } 12 | arr[arr.length - 1] = temp; 13 | } 14 | return arr; 15 | } 16 | 17 | // Time Complexity O(n) 18 | // Space Complexity O(n) 19 | function rotateLeft(d, arr) { 20 | d %= arr.length; 21 | const rotatedArray = []; 22 | for (let i = d; i < arr.length; i++) { 23 | rotatedArray[i - d] = arr[i]; 24 | } 25 | for (let i = 0, j = arr.length - d; i < d; i++, j++) { 26 | rotatedArray[j] = arr[i]; 27 | } 28 | return rotatedArray; 29 | } 30 | -------------------------------------------------------------------------------- /Arrays/SubarrayWithGivenSum.java: -------------------------------------------------------------------------------- 1 | // Subarray with given sum 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public static ArrayList subArrSum(int[] arr, int n, int s){ 7 | int i = 0; 8 | int j = 0; 9 | int sum = 0; 10 | ArrayList ans = new ArrayList<>(); 11 | while (i < n) { 12 | if (sum < s) { 13 | if (j >= n) { 14 | break; 15 | } 16 | sum += arr[j]; 17 | j++; 18 | } else if (sum > s) { 19 | sum -= arr[i]; 20 | i++; 21 | } else { 22 | ans.add(i + 1); 23 | ans.add(j); 24 | return ans; 25 | } 26 | } 27 | ans.add(-1); 28 | return ans; 29 | } 30 | -------------------------------------------------------------------------------- /Arrays/SummaryRanges.js: -------------------------------------------------------------------------------- 1 | // 228. Summary Ranges 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var summaryRanges = function(nums) { 7 | if (!nums.length) return []; 8 | let start = nums[0]; 9 | let end = nums[0]; 10 | const ans = []; 11 | for (let i = 0; i < nums.length; i++) { 12 | if (i < nums.length - 1 && nums[i] == nums[i + 1] - 1) { 13 | end = nums[i + 1]; 14 | } else { 15 | if (start == end) ans.push(`${start}`); 16 | else ans.push(`${start}->${end}`); 17 | start = nums[i + 1]; 18 | end = nums[i + 1]; 19 | } 20 | } 21 | return ans; 22 | }; 23 | 24 | // Look ahead approach 25 | -------------------------------------------------------------------------------- /Arrays/ThirdMaximumNumber.js: -------------------------------------------------------------------------------- 1 | // Find the third maximum number in the array if it doesn't exist return the largest nuber 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var thirdMax = function (nums) { 7 | let first = Number.MIN_SAFE_INTEGER; 8 | let second = Number.MIN_SAFE_INTEGER; 9 | let third = Number.MIN_SAFE_INTEGER; 10 | 11 | for (let i = 0; i < nums.length; i++) { 12 | if (nums[i] == first || nums[i] == second || nums[i] == third) continue; 13 | if (nums[i] > first) { 14 | third = second; 15 | second = first; 16 | first = nums[i]; 17 | } else if (nums[i] > second) { 18 | third = second; 19 | second = nums[i]; 20 | } else if (nums[i] > third) { 21 | third = nums[i]; 22 | } 23 | } 24 | if (third == Number.MIN_SAFE_INTEGER) return first; 25 | else return third; 26 | }; 27 | -------------------------------------------------------------------------------- /Arrays/TwoSum.js: -------------------------------------------------------------------------------- 1 | // Return index of two elements in the array (nums) which add up to the target 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | function twoSum(nums, target) { 7 | const map = new Map(); 8 | 9 | for(let [i, num] of nums.entries()){ 10 | if(map.has(target - num)){ 11 | return [map.get(target - num), i]; 12 | } else{ 13 | map.set(num,i); 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Arrays/TwoSumSorted.js: -------------------------------------------------------------------------------- 1 | // Given a sorted array return the index of two elements which add upto the target 2 | 3 | // Time Complexity O(n) 4 | // Space Complextiy O(1) 5 | 6 | function twoSum(numbers, target) { 7 | let i = 0; 8 | let j = numbers.length - 1; 9 | while (i < j) { 10 | if (numbers[i] + numbers[j] == target) 11 | return [i+1, j+1]; 12 | else if (numbers[i] + numbers[j] > target) 13 | j--; 14 | else 15 | i++; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /BasicProblems/BenjaminBulbs.js: -------------------------------------------------------------------------------- 1 | // 1. You are given n number of bulbs. They are all switched off. A weird fluctuation in voltage hits the circuit n times. 2 | // In the 1st fluctuation all bulbs are toggled, in the 2nd fluctuation every 2nd bulb is toggled, in the 3rd fluctuation every 3rd bulb is toggled and so on. 3 | // You've to find which bulbs will be switched on after n fluctuations. 4 | // 2. Take as input a number n, representing the number of bulbs. 5 | // 3. Print all the bulbs that will be on after the nth fluctuation in voltage. 6 | 7 | function benjaminBulbs(n) { 8 | for (let i = 1; i * i <= n; i++) 9 | console.log(i * i); 10 | } 11 | 12 | // All the bulbs having an odd no of factors remain on it the end 13 | // Even prime numbers would be turned off because they have two factors 1 and the number itself 14 | // 1 * 7 | 7 * 1 15 | 16 | // All the perfect squares have odd no of factors 17 | // 1 * 36 | 36 * 1 18 | // 2 * 18 | 18 * 2 19 | // 3 * 12 | 12 * 3 20 | // 4 * 9 | 9 * 4 21 | // 6 * 6 << this becomes the odd factor 22 | -------------------------------------------------------------------------------- /BasicProblems/CountDigits.js: -------------------------------------------------------------------------------- 1 | // Count the number of digits in a number 2 | 3 | // Time Complexity O(log(n)) 4 | // Space Complexity O(1) 5 | 6 | function countDigits(num) { 7 | let count = 0; 8 | while (num != 0) { 9 | num = Math.floor(num / 10); 10 | 11 | count++; 12 | } 13 | return count; 14 | } 15 | -------------------------------------------------------------------------------- /BasicProblems/Gcd&Lcm.js: -------------------------------------------------------------------------------- 1 | // Calculate GCD and LCM of a and b 2 | 3 | // Time Complexity O(log(min(m,n))) 4 | // Space Complexity O(1) 5 | 6 | 7 | // Eulclids Algorithm for GCD 8 | 9 | // a )▔▔ 10 | // b 11 | // ▔▔ 12 | // b % a)▔▔ ie the remainder (b%a) will be the new a 13 | // a and a will be the new b 14 | // ▔▔ 15 | // ....... 16 | 17 | function gcd(a, b) { 18 | if (a == 0) return b; 19 | return gcd(b % a, a); 20 | } 21 | 22 | // a * b = GCD * LCM >> so LCM can be found after finding GCD 23 | -------------------------------------------------------------------------------- /BasicProblems/InverseOfANumber.js: -------------------------------------------------------------------------------- 1 | // Question 2 | // if the number is 5 digits long, it'll contain all the digits from 1 to 5 without missing and repeating any digit from 1 to 5 3 | // If we have a number 426135 here we can see that 5 is in the 1st position and 3 is in the 2nd position 4 | // To calculate inverse of a number we'll put 1 in the 5th place and 2 in the 3rd place doing so for all the digits 5 | // so the inverse would be 416253 6 | 7 | // Time Complexity O(log(n)) 8 | // Space Complexity O(1) 9 | 10 | function inverseOfANumber(num) { 11 | let ans = 0; 12 | let count = 1; 13 | while (num != 0) { 14 | let power = num % 10; 15 | num = Math.floor(num / 10); 16 | ans += count * Math.pow(10, power - 1); 17 | count++; 18 | } 19 | return ans; 20 | } 21 | -------------------------------------------------------------------------------- /BasicProblems/PrimeFactors.js: -------------------------------------------------------------------------------- 1 | // print the prime factors of a number 2 | // eg n = 1440 >> 2 2 2 2 2 3 3 5 3 | 4 | function primeFactors(n) { 5 | while (n != 1) { 6 | for (let i = 2; i * i <= n; i++) { 7 | if (n % i == 0) { 8 | console.log(i + " "); 9 | n = Math.floor(n / i); 10 | break; 11 | } 12 | if (i == Math.floor(Math.sqrt(n))) { 13 | // if we reach √n and still haven't found a factor then the number is prime 14 | console.log(n + " "); 15 | n = Math.floor(n / n); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /BasicProblems/PrimeNo.js: -------------------------------------------------------------------------------- 1 | // Check if the number is prime or composite 2 | 3 | // We won't find any new factors for 36 after the square root of the number 4 | // 1 * 36 | 36 * 1 5 | // 2 * 18 | 18 * 2 6 | // 3 * 12 | 12 * 3 7 | // 4 * 9 | 9 * 4 8 | // 6 * 6 | 6 * 6 9 | 10 | // Time Complexity O(√n) 11 | // Space Complexity O(1) 12 | 13 | function checkPrime(n) { 14 | if (n < 0) return "Invalid Input"; 15 | if (n < 2) return "It's neither prime nor composite"; 16 | if (n == 2) return "It's a prime number"; 17 | for (let i = 2; i * i <= n; i++) 18 | if (n % i == 0) return "It's a composite number"; 19 | return "It's a prime number"; 20 | } 21 | -------------------------------------------------------------------------------- /BasicProblems/PrintDigits.js: -------------------------------------------------------------------------------- 1 | // Print the digits of a number from left to right 2 | 3 | // Time Complexity O(log(n)) 4 | // Space Complexity O(1) 5 | 6 | function printDigits(num) { 7 | let count = 0; 8 | let temp = num; 9 | while (temp != 0) { 10 | temp = Math.floor(temp / 10); 11 | count++; 12 | } 13 | while (count != 0) { 14 | // A number like 3000 will be an edge case if we check for num != 0 15 | let digit = Math.floor(num / Math.pow(10, count - 1)); 16 | num %= Math.pow(10, count - 1); 17 | count--; 18 | console.log(digit); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /BasicProblems/PrintFibonacci.js: -------------------------------------------------------------------------------- 1 | // Print the first n Fibonacci Numbers 2 | 3 | // we shift a and b with each iteration and keep printing a. 4 | // 0 1 1 2 3 5 8 5 | // a b 6 | // a b 7 | // a b 8 | 9 | // Time Complexity O(n) 10 | // Space Complexity O(1) 11 | 12 | function printFibonacci(n) { 13 | let a = 0; 14 | let b = 1; 15 | for (let i = 0; i < n; i++) { 16 | console.log(a + " "); 17 | let nextNum = a + b; 18 | a = b; 19 | b = nextNum; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /BasicProblems/PythagoreanTriplet.js: -------------------------------------------------------------------------------- 1 | // check if the numbers are Pythagorean triplets 2 | 3 | function pythagoreanTriplet(a, b, c) { 4 | let hypo = Math.max(Math.max(a, b), c); 5 | if (a == hypo) 6 | return Math.pow(hypo, 2) == Math.pow(b, 2) + Math.pow(c, 2); 7 | else if (b == hypo) 8 | return Math.pow(hypo, 2) == Math.pow(a, 2) + Math.pow(c, 2); 9 | else 10 | return Math.pow(hypo, 2) == Math.pow(b, 2) + Math.pow(a, 2); 11 | } 12 | -------------------------------------------------------------------------------- /BasicProblems/README.md: -------------------------------------------------------------------------------- 1 | The time complexity in some problems is log(n) because we are dividing the number (ie the input) by a scale of 10. Or we could say that the time complexity would be given by the number of the digits in the number which is approximately equal to log(n). 2 | 3 | ### Questions with an optimal solution 4 | - [Sieve of Eratosthenes](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/SieveOfEratosthenes.js) 5 | - [GCD and LCM](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/Gcd&Lcm.js) 6 | - [Rotate A Number](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/RotateANumber.js) 7 | - [Prime Number](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/PrimeNo.js) 8 | - [Prime Factors](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/PrimeFactors.js) 9 | 10 | ### Questions with edge cases 11 | - [Rotate A Number](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/RotateANumber.js) 12 | - when k is greater than no of digits 13 | - when num = 0 14 | - when k is negative 15 | - [Print Digits](https://github.com/RohitDhatrak/DS-Algo/blob/main/BasicProblems/PrintDigits.js) 16 | - when we have a number ending with zero/zeros 17 | -------------------------------------------------------------------------------- /BasicProblems/ReverseANumber.js: -------------------------------------------------------------------------------- 1 | // Reverse an integer number 2 | 3 | // Time Complexity O(log(n)) 4 | // Space Complexity O(1) 5 | 6 | function reverseNumber(num) { 7 | let count = 0; 8 | let temp = num; 9 | let ans = 0; 10 | while (temp != 0) { 11 | temp = Math.floor(temp / 10); 12 | count++; 13 | } 14 | while (num != 0) { 15 | let digit = num % 10; 16 | num = Math.floor(num / 10); 17 | ans += digit * Math.pow(10, count - 1); 18 | count--; 19 | } 20 | return ans; 21 | } 22 | -------------------------------------------------------------------------------- /BasicProblems/RotateANumber.js: -------------------------------------------------------------------------------- 1 | // Rotate a number k times (if k is positive rotate right if negative rotate left) 2 | // k can be greater than the number of digits 3 | 4 | // Time Complexity O(log(n)) 5 | // Space Complexity O(1) 6 | 7 | function rotateNumber(num, k) { 8 | let temp = num; 9 | let size = 0; 10 | while (temp != 0) { 11 | temp = Math.floor(temp / 10); 12 | size++; 13 | } 14 | 15 | if (size == 0) 16 | // edge case num = 0 17 | return num; 18 | 19 | if (k < 0) { 20 | // edge case if k is -ve and greater than length 21 | k = -k; 22 | if (k >= size) k %= size; 23 | k = size - k; 24 | } 25 | 26 | if (k >= size) 27 | // edge case if k is greater than length 28 | k %= size; 29 | 30 | if (k == 0) return num; 31 | 32 | let digits = num % Math.pow(10, k); 33 | num = Math.floor(num / Math.pow(10, k)); 34 | 35 | digits *= Math.pow(10, size - k); 36 | num += digits; 37 | 38 | return num; 39 | } 40 | -------------------------------------------------------------------------------- /BasicProblems/SieveOfEratosthenes.js: -------------------------------------------------------------------------------- 1 | // Sieve of Eratosthenes - gives prime numbers between 2 to n 2 | 3 | // Time Complexity O(n*log(log(n))) 4 | // Space Complexity O(n) 5 | 6 | function sieve(n) { 7 | let arr = []; 8 | for (let i = 2; i <= n; i++) arr[i - 2] = i; 9 | 10 | for (let i = 2; i * i <= n; i++) { 11 | // we stop if the square of i is greater than n 12 | if (arr[i - 2] != 0) { 13 | // if the number is marked then all it's factors are marked so we move to the next number 14 | for (let j = Math.pow(i, 2); j <= n; j++) { 15 | // we start checking from i^2 because all the previous factors of i would be already marked 16 | if (arr[j - 2] % i == 0) arr[j - 2] = 0; 17 | } 18 | } 19 | } 20 | return arr; 21 | } 22 | -------------------------------------------------------------------------------- /Bit Manipulation/Basics.js: -------------------------------------------------------------------------------- 1 | // Basic operations like get bit, set bit, clear bit & update bit 2 | 3 | function getBit(n, pos) { 4 | // get the bit at pos 5 | console.log("log" + (n & (1 << pos))); 6 | if (n & (1 << pos)) 7 | return 1; 8 | else 9 | return 0; 10 | } 11 | 12 | function setBit(n, pos) { 13 | // set the bit at pos 14 | return n | (1 << pos); 15 | } 16 | 17 | function clearBit(n, pos) { 18 | // clear the bit at pos 19 | return n & ~(1 << pos); 20 | } 21 | 22 | function updateBit(n, pos, val) { 23 | // update the bit at pos with give val 24 | if (val == 1) 25 | return setBit(n, pos); 26 | else 27 | return clearBit(n, pos); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Bit Manipulation/DivisibleBy2.js: -------------------------------------------------------------------------------- 1 | // check if the number is divisible by 2 2 | 3 | function powerOf2(num) { 4 | let ans = num & 1; // we check if the last bit is zero 5 | if (ans == 0) 6 | return true; 7 | else 8 | return false; 9 | } 10 | -------------------------------------------------------------------------------- /Bit Manipulation/FindUnique.java: -------------------------------------------------------------------------------- 1 | // Find the unique number in the array (every other number occurs twice) 2 | // 136. Single Number 3 | 4 | public int singleNumber(int[] nums) { 5 | int num = 0; 6 | for (int i = 0; i < nums.length; i++) { 7 | num = num ^ nums[i]; 8 | } 9 | return num; 10 | } 11 | -------------------------------------------------------------------------------- /Bit Manipulation/FindUnique.js: -------------------------------------------------------------------------------- 1 | // Find the unique number in the array (every other number occurs twice) 2 | // 136. Single Number 3 | 4 | function findUnique(arr) { 5 | let num = 0; 6 | for (let i = 0; i < arr.length; i++) { 7 | num = num ^ arr[i]; 8 | } 9 | return num; 10 | } 11 | 12 | // Find two unique numbers from an array (every other number occurs twice) 13 | 14 | function find2Unique(arr) { 15 | let diff = 0; 16 | let oneNo = 0; 17 | let ans = []; 18 | for (let i = 0; i < arr.length; i++) { 19 | diff = diff ^ arr[i]; // this will give the diff btw the 2 unique num 20 | } 21 | for (let i = 0; i < arr.length; i++) { 22 | if ((arr[i] & diff) > 0) 23 | // we'll check all the numbers that have the diff 24 | oneNo = oneNo ^ arr[i]; // and xor them to find one of the unique numbers 25 | } 26 | ans[0] = oneNo; 27 | ans[1] = oneNo ^ diff; // by applying xor to the number and the diff we get the second unique number 28 | return ans; 29 | } 30 | 31 | // Find one unique numbers from an array (every other number occurs thrice) 32 | 33 | function findUnique3(arr) { 34 | let ans = 0; 35 | for (let i = 0; i < 64; i++) { 36 | // we count the no of set bits in all 64 places 37 | let count = 0; 38 | for (let j = 0; j < arr.length; j++) { 39 | if ((arr[j] & (1 << i)) > 0) count++; 40 | } 41 | if (count % 3 != 0) { 42 | // the count will be divisible by 3 if the number is repeated thrice 43 | ans = ans | (1 << i); 44 | } 45 | } 46 | return ans; 47 | } 48 | -------------------------------------------------------------------------------- /Bit Manipulation/MissingNumber.js: -------------------------------------------------------------------------------- 1 | // 268. Missing Number 2 | 3 | var missingNumber = function(nums) { 4 | let ans; 5 | for(let i = 0; i < nums.length; i++){ 6 | ans = ans ^ nums[i]; 7 | } 8 | for(let i = 0; i <= nums.length; i++){ 9 | ans = ans ^ i; 10 | } 11 | return ans 12 | }; 13 | 14 | // arrays 15 | var missingNumber = function(nums) { 16 | const expectedSum = (nums.length * (nums.length + 1)) / 2; 17 | const sum = nums.reduce((accum, num) => accum + num, 0); 18 | return expectedSum - sum 19 | }; 20 | -------------------------------------------------------------------------------- /Bit Manipulation/NoOf1s.js: -------------------------------------------------------------------------------- 1 | // count the no of ones in the binary representation of the number 2 | 3 | function noOf1s(num) { 4 | let count = 0; 5 | while (num > 0) { 6 | num = num & (num - 1); 7 | count++; 8 | } 9 | return count; 10 | } 11 | -------------------------------------------------------------------------------- /Bit Manipulation/README.md: -------------------------------------------------------------------------------- 1 | ### Good Problems 2 | - [Find unique numbers](https://github.com/RohitDhatrak/DS-Algo/blob/main/Bit%20Manipulation/FindUnique.js) 3 | - [No of 1s](https://github.com/RohitDhatrak/DS-Algo/blob/main/Bit%20Manipulation/NoOf1s.js) 4 | - [Print subsets](https://github.com/RohitDhatrak/DS-Algo/blob/main/Bit%20Manipulation/SubSet.js) 5 | -------------------------------------------------------------------------------- /Bit Manipulation/SubSet.js: -------------------------------------------------------------------------------- 1 | // print all the possible subsets of the array 2 | 3 | function subSets(arr) { 4 | for (let i = 0; i < Math.pow(2, arr.length); i++) { 5 | for (let j = 0; j < arr.length; j++) { 6 | if ((i & (1 << j)) > 0) { 7 | process.stdout.write(arr[j] + " "); 8 | } 9 | } 10 | console.log(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Data Structures/Java/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/BST.js: -------------------------------------------------------------------------------- 1 | const Queue = require("./Queue"); 2 | 3 | class Node { 4 | constructor(value) { 5 | this.value = value; 6 | this.left = null; 7 | this.right = null; 8 | this.occurance = 1; 9 | } 10 | } 11 | 12 | class BST { 13 | #root; 14 | #size; 15 | 16 | constructor() { 17 | this.#root = null; 18 | this.#size = 0; 19 | } 20 | 21 | /* Inserts a node into the BST O(logn) */ 22 | insert(value) { 23 | if (this.#root) { 24 | let node = this.#root; 25 | let positionIsFound = false; 26 | while (!positionIsFound) { 27 | if (value < node.value) { 28 | if (node.left) node = node.left; 29 | else { 30 | node.left = new Node(value); 31 | positionIsFound = true; 32 | } 33 | } else if (value > node.value) { 34 | if (node.right) node = node.right; 35 | else { 36 | node.right = new Node(value); 37 | positionIsFound = true; 38 | } 39 | } else { 40 | node.occurance++; 41 | return this.#root; 42 | } 43 | } 44 | } else { 45 | this.#root = new Node(value); 46 | } 47 | this.#size++; 48 | return this.#root; 49 | } 50 | 51 | /* Returns a boolean indicating whether the value is present in the BST O(logn) */ 52 | contains(value) { 53 | let node = this.#root; 54 | while (node) { 55 | if (value < node.value) { 56 | node = node.left; 57 | } else if (value > node.value) { 58 | node = node.right; 59 | } else if (value === node.value) { 60 | return true; 61 | } else { 62 | return false; 63 | } 64 | } 65 | return false; 66 | } 67 | 68 | /* If we pass a specific value to search it returns a boolean indicating whether the value is present in the BST 69 | 70 | If we dont pass a specific value to search then it returns an array of all the nodes in breadth-first order 71 | */ 72 | 73 | BFS(value) { 74 | const visited = []; 75 | const queue = new Queue(); 76 | queue.enqueue(this.#root); 77 | 78 | while (queue.length > 0) { 79 | const currentNode = queue.dequeue(); 80 | 81 | if (value && value === currentNode.value) { 82 | return true; 83 | } else if (!value) { 84 | visited.push(currentNode.value); 85 | } 86 | 87 | if (currentNode.left) { 88 | queue.enqueue(currentNode.left); 89 | } 90 | if (currentNode.right) { 91 | queue.enqueue(currentNode.right); 92 | } 93 | } 94 | 95 | if (value) { 96 | return false; 97 | } 98 | return visited; 99 | } 100 | 101 | DFS({ type, value }) { 102 | const visited = []; 103 | let isFound = false; 104 | 105 | function traversePreOrder(node) { 106 | /* 107 | We traverse from top to bottom picking left side first at every node 108 | 109 | Root, Left, Right (pre order - we add the root before the children) 110 | 111 | usecase: to create a copy of the tree 112 | */ 113 | if (value && value === node.value) isFound = true; 114 | else if (!value) visited.push(node.value); 115 | 116 | if (node.left) traversePreOrder(node.left); 117 | if (node.right) traversePreOrder(node.right); 118 | } 119 | 120 | function traversePostOrder(node) { 121 | /* 122 | We traverse from the bottom to top starting from left side and then traversing the right side 123 | 124 | While traversing from bottom to top we pick the left node first then the right node and then the parent node. 125 | 126 | Left, Right, Root (post order - we add the root after the children) 127 | 128 | usecase: can be used to delete the tree 129 | */ 130 | if (node.left) traversePostOrder(node.left); 131 | if (node.right) traversePostOrder(node.right); 132 | 133 | if (value && value === node.value) isFound = true; 134 | else if (!value) visited.push(node.value); 135 | } 136 | 137 | function traverseInOrder(node) { 138 | /* 139 | Same as post order we traverse from the bottom to top starting from left side and then traversing the right side 140 | 141 | While traversing from bottom to top we pick the left node first node and then the parent node then the right 142 | 143 | Left, Root, Right 144 | 145 | usecase: returns the nodes in increasing order (inorder) 146 | */ 147 | if (node.left) traverseInOrder(node.left); 148 | if (value && value === node.value) isFound = true; 149 | else if (!value) visited.push(node.value); 150 | if (node.right) traverseInOrder(node.right); 151 | } 152 | 153 | if (type === "postorder") traversePostOrder(this.#root); 154 | else if (type === "inorder") traverseInOrder(this.#root); 155 | else traversePreOrder(this.#root); 156 | 157 | if (value) { 158 | return isFound; 159 | } 160 | return visited; 161 | } 162 | 163 | get size() { 164 | return this.#size; 165 | } 166 | } 167 | 168 | module.exports = BST; 169 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/DoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Node { 4 | constructor(value, prev) { 5 | this.value = value; 6 | this.next = null; 7 | this.prev = prev; 8 | } 9 | } 10 | 11 | class DoublyLinkedList { 12 | #head; 13 | #tail; 14 | #length; 15 | 16 | constructor() { 17 | this.#head = null; 18 | this.#tail = null; 19 | this.#length = 0; 20 | } 21 | 22 | /* Add a node to the end of the list O(1) */ 23 | push(value) { 24 | if (this.#head) { 25 | this.#tail.next = new Node(value, this.#tail); 26 | this.#tail = this.#tail.next; 27 | } else { 28 | this.#head = new Node(value, null); 29 | this.#tail = this.#head; 30 | } 31 | this.#length++; 32 | return this; 33 | } 34 | 35 | /* Remove the last node from the list O(1) */ 36 | pop() { 37 | const lastNode = this.#tail; 38 | if (!this.#head) { 39 | return undefined; 40 | } else if (this.#length === 1) { 41 | this.#head = null; 42 | this.#tail = null; 43 | } else { 44 | this.#tail = lastNode.prev; 45 | this.#tail.next = null; 46 | lastNode.prev = null; 47 | } 48 | this.#length--; 49 | return lastNode; 50 | } 51 | 52 | /* Remove the first node from the list O(1) */ 53 | shift() { 54 | const firstNode = this.#head; 55 | if (!this.#head) { 56 | return undefined; 57 | } else if (this.#length === 1) { 58 | this.#head = null; 59 | this.#tail = null; 60 | } else { 61 | this.#head = firstNode.next; 62 | this.#head.prev = null; 63 | firstNode.next = null; 64 | } 65 | this.#length--; 66 | return firstNode; 67 | } 68 | 69 | /* Add a new node to the beginning of the list O(1) */ 70 | unshift(value) { 71 | if (!this.#head) { 72 | return this.push(value); 73 | } else { 74 | const newNode = new Node(value, null); 75 | this.#head.prev = newNode; 76 | newNode.next = this.#head; 77 | this.#head = newNode; 78 | this.#length++; 79 | return this; 80 | } 81 | } 82 | 83 | /* Get the value of the node at the given position O(n) */ 84 | get(position) { 85 | if (position < 0 || position >= this.#length) { 86 | return undefined; 87 | } else if (position < this.#length / 2) { 88 | let node = this.#head; 89 | while (position !== 0) { 90 | node = node.next; 91 | position--; 92 | } 93 | return node.value; 94 | } else { 95 | let node = this.#tail; 96 | while (position < this.#length - 1) { 97 | node = node.prev; 98 | position++; 99 | } 100 | return node.value; 101 | } 102 | } 103 | 104 | /* Private property to get node at the given position O(n) */ 105 | #getNode(position) { 106 | if (position < 0 || position >= this.#length) { 107 | return undefined; 108 | } else if (position < this.#length / 2) { 109 | let node = this.#head; 110 | while (position !== 0) { 111 | node = node.next; 112 | position--; 113 | } 114 | return node; 115 | } else { 116 | let node = this.#tail; 117 | while (position < this.#length - 1) { 118 | node = node.prev; 119 | position++; 120 | } 121 | return node; 122 | } 123 | } 124 | 125 | /* Change the value of the node at the given position O(n) */ 126 | set(position, value) { 127 | const node = this.#getNode(position); 128 | if (node) { 129 | node.value = value; 130 | return true; 131 | } 132 | return undefined; 133 | } 134 | 135 | /* Insert a node at the given position O(1) or O(n) */ 136 | insert(position, value) { 137 | if (position < 0 || position >= this.#length) { 138 | return undefined; 139 | } else if (position === 0) { 140 | this.unshift(value); 141 | } else { 142 | const prevNode = this.#getNode(position - 1); 143 | const newNode = new Node(value, prevNode); 144 | const nextNode = prevNode.next; 145 | newNode.next = nextNode; 146 | nextNode.prev = newNode; 147 | prevNode.next = newNode; 148 | this.#length++; 149 | } 150 | return true; 151 | } 152 | 153 | /* Remove the node at the given position O(1) or O(n) */ 154 | remove(position) { 155 | if (position < 0 || position >= this.#length) { 156 | return undefined; 157 | } else if (position === 0) { 158 | this.shift(); 159 | } else if (position === this.length - 1) { 160 | this.pop(); 161 | } else { 162 | const prevNode = this.#getNode(position - 1); 163 | const nodeToBeRemoved = prevNode.next; 164 | nodeToBeRemoved.next.prev = prevNode; 165 | prevNode.next = nodeToBeRemoved.next; 166 | nodeToBeRemoved.next = null; 167 | nodeToBeRemoved.prev = null; 168 | this.#length--; 169 | } 170 | return true; 171 | } 172 | 173 | get length() { 174 | return this.#length; 175 | } 176 | } 177 | 178 | module.exports = DoublyLinkedList; 179 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/Queue.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Node { 4 | constructor(value, prev) { 5 | this.value = value; 6 | this.prev = prev; 7 | this.next = null; 8 | } 9 | } 10 | 11 | class Queue { 12 | #head; 13 | #tail; 14 | #length; 15 | 16 | constructor() { 17 | this.#head = null; 18 | this.#tail = null; 19 | this.#length = 0; 20 | } 21 | 22 | /* Adds an element to the end of the queue O(1)*/ 23 | enqueue(element) { 24 | if (this.#head) { 25 | this.#tail.next = new Node(element, this.#tail); 26 | this.#tail = this.#tail.next; 27 | } else { 28 | this.#head = new Node(element, null); 29 | this.#tail = this.#head; 30 | } 31 | this.#length++; 32 | } 33 | 34 | /* Removes the first element in the queue O(1)*/ 35 | dequeue() { 36 | const firstElement = this.#head; 37 | if (!this.#head) return undefined; 38 | else if (this.length === 1) { 39 | this.#head = null; 40 | this.#tail = null; 41 | } else { 42 | this.#head = firstElement.next; 43 | firstElement.next = null; 44 | this.#head.prev = null; 45 | } 46 | this.#length--; 47 | return firstElement.value; 48 | } 49 | 50 | /* Returns the first element in the queue without removing it O(1) */ 51 | peek() { 52 | if (!this.#head) return undefined; 53 | return this.#head.value; 54 | } 55 | 56 | get length() { 57 | return this.#length; 58 | } 59 | } 60 | 61 | module.exports = Queue; 62 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/SinglyLinkedList.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Node { 4 | constructor(value) { 5 | this.value = value; 6 | this.next = null; 7 | } 8 | } 9 | 10 | class SinglyLinkedList { 11 | #head; 12 | #tail; 13 | #length; 14 | 15 | constructor() { 16 | this.#head = null; 17 | this.#tail = null; 18 | this.#length = 0; 19 | } 20 | 21 | /* Add a node to the end of the list O(1) */ 22 | push(value) { 23 | if (this.#head) { 24 | this.#tail.next = new Node(value); 25 | this.#tail = this.#tail.next; 26 | } else { 27 | this.#head = new Node(value); 28 | this.#tail = this.#head; 29 | } 30 | this.#length++; 31 | return this; 32 | } 33 | 34 | /* Remove the last node from the list O(n) */ 35 | pop() { 36 | let newTail = this.#head; 37 | if (!this.#head) { 38 | return undefined; 39 | } else if (this.#length === 1) { 40 | this.#head = null; 41 | this.#tail = null; 42 | this.#length = 0; 43 | return newTail; 44 | } else { 45 | for (let i = 0; i < this.#length - 2; i++) { 46 | newTail = newTail.next; 47 | } 48 | const lastNode = newTail.next; 49 | newTail.next = null; 50 | this.#tail = newTail; 51 | this.#length--; 52 | return lastNode; 53 | } 54 | } 55 | 56 | /* Remove the first node from the list O(1) */ 57 | shift() { 58 | if (!this.#head) { 59 | return undefined; 60 | } else if (this.#length === 1) { 61 | return this.pop(); 62 | } else { 63 | const firstNode = this.#head; 64 | this.#head = firstNode.next; 65 | firstNode.next = null; 66 | this.#length--; 67 | return firstNode; 68 | } 69 | } 70 | 71 | /* Add a new node to the beginning of the list O(1) */ 72 | unshift(value) { 73 | if (!this.#head) { 74 | return this.push(value); 75 | } else { 76 | const newNode = new Node(value); 77 | newNode.next = this.#head; 78 | this.#head = newNode; 79 | this.#length++; 80 | return this; 81 | } 82 | } 83 | 84 | /* Get the value of the node at the given position O(n) */ 85 | get(position) { 86 | if (position >= this.#length || position < 0) { 87 | return undefined; 88 | } 89 | let node = this.#head; 90 | while (position !== 0) { 91 | node = node.next; 92 | position--; 93 | } 94 | return node.value; 95 | } 96 | 97 | /* Private property to get node at the given position O(n) */ 98 | #getNode(position) { 99 | if (position >= this.#length || position < 0) { 100 | return undefined; 101 | } 102 | let node = this.#head; 103 | while (position !== 0) { 104 | node = node.next; 105 | position--; 106 | } 107 | return node; 108 | } 109 | 110 | /* Change the value of the node at the given position O(n) */ 111 | set(position, value) { 112 | const node = this.#getNode(position); 113 | if (node) { 114 | node.value = value; 115 | return true; 116 | } 117 | return undefined; 118 | } 119 | 120 | /* Insert a node at the given position O(1) or O(n) */ 121 | insert(position, value) { 122 | if (position >= this.#length || position < 0) { 123 | return undefined; 124 | } else if (position === 0) { 125 | this.unshift(value); 126 | } else { 127 | const prevNode = this.#getNode(position - 1); 128 | const newNode = new Node(value); 129 | newNode.next = prevNode.next; 130 | prevNode.next = newNode; 131 | this.#length++; 132 | } 133 | return true; 134 | } 135 | 136 | /* Remove the node at the given position O(1) or O(n) */ 137 | remove(position) { 138 | if (position >= this.#length || position < 0) { 139 | return undefined; 140 | } else if (position === 0) { 141 | this.shift(); 142 | } else { 143 | const node = this.#getNode(position); 144 | const prevNode = this.#getNode(position - 1); 145 | prevNode.next = node.next; 146 | this.#length--; 147 | } 148 | return true; 149 | } 150 | 151 | /* Reverses the order of the list in place O(n) */ 152 | reverse() { 153 | this.#tail = this.#head; 154 | let currentNode = this.#head; 155 | let nextNode = currentNode.next; 156 | let prevNode = currentNode; 157 | while (nextNode) { 158 | currentNode = nextNode; 159 | nextNode = currentNode.next; 160 | currentNode.next = prevNode; 161 | prevNode = currentNode; 162 | } 163 | this.#tail.next = null; 164 | this.#head = currentNode; 165 | return this; 166 | } 167 | 168 | /* Get the length of the list */ 169 | get length() { 170 | return this.#length; 171 | } 172 | } 173 | 174 | module.exports = SinglyLinkedList; 175 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/Stack.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Node { 4 | constructor(value, prev) { 5 | this.value = value; 6 | this.prev = prev; 7 | this.next = null; 8 | } 9 | } 10 | 11 | class Stack { 12 | #head; 13 | #tail; 14 | #size; 15 | 16 | constructor() { 17 | this.#head = null; 18 | this.#tail = null; 19 | this.#size = 0; 20 | } 21 | 22 | /* Add a element on top of the stack O(1) */ 23 | push(value) { 24 | if (this.#head) { 25 | this.#tail.next = new Node(value, this.#tail); 26 | this.#tail = this.#tail.next; 27 | } else { 28 | this.#head = new Node(value, null); 29 | this.#tail = this.#head; 30 | } 31 | this.#size++; 32 | return this; 33 | } 34 | 35 | /* Remove the element at the top of the stack and returns it O(1)*/ 36 | pop() { 37 | const lastElement = this.#tail; 38 | if (!this.#head) return undefined; 39 | else if (this.#size === 1) { 40 | this.#head = null; 41 | this.#tail = null; 42 | } else { 43 | this.#tail = lastElement.prev; 44 | lastElement.prev = null; 45 | this.#tail.next = null; 46 | } 47 | this.#size--; 48 | return lastElement.value; 49 | } 50 | 51 | /* Returns the value of the element at the top of the stack without removing it O(1)*/ 52 | peek() { 53 | if (!this.#head) return undefined; 54 | else { 55 | return this.#tail.value; 56 | } 57 | } 58 | 59 | get size() { 60 | return this.#size; 61 | } 62 | } 63 | 64 | module.exports = Stack; 65 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dsalgo", 3 | "version": "1.0.0", 4 | "description": "Repository for Data Structures in JavaScript", 5 | "main": "algo.js", 6 | "scripts": { 7 | "test": "jest" 8 | }, 9 | "keywords": [ 10 | "dsa", 11 | "javascript" 12 | ], 13 | "author": "Rohit Dhatrak", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "jest": "^27.0.6" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/tests/BST.test.js: -------------------------------------------------------------------------------- 1 | const BST = require("../BST.js"); 2 | 3 | const bst = new BST(); 4 | 5 | test("Initalization of the BST", () => { 6 | expect(bst.size).toBe(0); 7 | }); 8 | 9 | test("Insertion method of the BST", () => { 10 | expect(bst.insert(10).value).toBe(10); 11 | expect(bst.size).toBe(1); 12 | bst.insert(10); 13 | expect(bst.size).toBe(1); 14 | bst.insert(5); 15 | bst.insert(4); 16 | bst.insert(13); 17 | bst.insert(7); 18 | expect(bst.size).toBe(5); 19 | }); 20 | 21 | /* 22 | 10(2) 23 | / \ 24 | 5 13 25 | / \ 26 | 4 7 27 | */ 28 | 29 | test("Testing contains method of the BST", () => { 30 | expect(bst.contains(10)).toBe(true); 31 | expect(bst.contains(13)).toBe(true); 32 | expect(bst.contains(5)).toBe(true); 33 | expect(bst.contains(4)).toBe(true); 34 | expect(bst.contains(7)).toBe(true); 35 | expect(bst.contains(15)).toBe(false); 36 | expect(bst.contains(undefined)).toBe(false); 37 | expect(bst.contains(null)).toBe(false); 38 | expect(bst.contains("hello")).toBe(false); 39 | expect(bst.contains("5")).toBe(false); 40 | }); 41 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/tests/DoublyLinkedList.test.js: -------------------------------------------------------------------------------- 1 | const DoublyLinkedList = require("../DoublyLinkedList"); 2 | 3 | const list = new DoublyLinkedList(); 4 | 5 | test("Testing inialization of a doubly linked list", () => { 6 | expect(list.length).toBe(0); 7 | expect(list.head).toBe(undefined); 8 | expect(list.tail).toBe(undefined); 9 | }); 10 | 11 | test("Testing push method of doubly linked list", () => { 12 | expect(list.push(1)).toBe(list); 13 | expect(list.length).toBe(1); 14 | expect(list.get(0)).toBe(1); 15 | list.push(32); 16 | expect(list.get(1)).toBe(32); 17 | }); 18 | // 1 <-> 32 19 | 20 | test("Testing pop method of doubly linked list", () => { 21 | const popedNode = list.pop(); 22 | expect(popedNode.value).toBe(32); 23 | expect(popedNode.next).toBe(null); 24 | list.pop(); 25 | expect(list.length).toBe(0); 26 | expect(list.pop()).toBe(undefined); 27 | list.push(23); 28 | list.push(3); 29 | list.push(2); 30 | expect(list.pop().value).toBe(2); 31 | expect(list.length).toBe(2); 32 | }); 33 | // 23 <-> 3 34 | 35 | test("Testing shift method of doubly linked list", () => { 36 | const shiftedNode = list.shift(); 37 | expect(shiftedNode.value).toBe(23); 38 | expect(shiftedNode.next).toBe(null); 39 | expect(list.shift().value).toBe(3); 40 | expect(list.length).toBe(0); 41 | expect(list.shift()).toBe(undefined); 42 | }); 43 | // null 44 | 45 | test("Testing unshift method of doubly linked list", () => { 46 | expect(list.unshift(45)).toBe(list); 47 | expect(list.get(0)).toBe(45); 48 | expect(list.unshift(2)).toBe(list); 49 | expect(list.get(0)).toBe(2); 50 | expect(list.length).toBe(2); 51 | }); 52 | // 2 <-> 45 53 | 54 | test("Testing get method of doubly linked list", () => { 55 | expect(list.get(-2)).toBe(undefined); 56 | expect(list.get(200)).toBe(undefined); 57 | expect(list.get(2)).toBe(undefined); 58 | expect(list.get(0)).toBe(2); 59 | expect(list.get(1)).toBe(45); 60 | list.push(10); 61 | list.push(20); 62 | list.push(30); 63 | list.push(40); 64 | expect(list.get(2)).toBe(10); 65 | expect(list.get(3)).toBe(20); 66 | expect(list.get(4)).toBe(30); 67 | expect(list.get(5)).toBe(40); 68 | list.pop(); 69 | list.pop(); 70 | list.pop(); 71 | list.pop(); 72 | }); 73 | // 2 <-> 45 <-> 10 <-> 20 <-> 30 <-> 40 74 | 75 | test("Testing set method of doubly linked list", () => { 76 | expect(list.set(2, 100)).toBe(undefined); 77 | expect(list.set(0, 34)).toBe(true); 78 | expect(list.get(0)).toBe(34); 79 | expect(list.set(1, 25)).toBe(true); 80 | expect(list.get(1)).toBe(25); 81 | }); 82 | // 34 <-> 25 83 | 84 | test("Testing insert method of doubly linked list", () => { 85 | expect(list.insert(0, 19)).toBe(true); 86 | expect(list.get(0)).toBe(19); 87 | expect(list.length).toBe(3); 88 | expect(list.insert(3, 20)).toBe(undefined); 89 | expect(list.insert(2, 20)).toBe(true); 90 | expect(list.get(2)).toBe(20); 91 | expect(list.length).toBe(4); 92 | }); 93 | // 19 <-> 34 <-> 20 <-> 25 94 | 95 | test("Testing remove method of doubly linked list", () => { 96 | expect(list.remove(0)).toBe(true); 97 | expect(list.get(0)).toBe(34); 98 | expect(list.length).toBe(3); 99 | expect(list.remove(3)).toBe(undefined); 100 | expect(list.remove(2)).toBe(true); 101 | expect(list.length).toBe(2); 102 | expect(list.get(1)).toBe(20); 103 | expect(list.remove(1)).toBe(true); 104 | list.pop(); 105 | expect(list.length).toBe(0); 106 | }); 107 | // empty 108 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/tests/Queue.test.js: -------------------------------------------------------------------------------- 1 | const Queue = require("../Queue"); 2 | 3 | const queue = new Queue(); 4 | 5 | test("Testing initalization of a queue", () => { 6 | expect(queue.length).toBe(0); 7 | }); 8 | 9 | test("Testing enqueue method of queue", () => { 10 | queue.enqueue(1); 11 | expect(queue.length).toBe(1); 12 | queue.enqueue(2); 13 | queue.enqueue(3); 14 | expect(queue.length).toBe(3); 15 | }); 16 | // 1 < 2 < 3 17 | 18 | test("Testing dequeue method of queue", () => { 19 | queue.dequeue(); 20 | expect(queue.length).toBe(2); 21 | expect(queue.dequeue()).toBe(2); 22 | queue.dequeue(); 23 | expect(queue.length).toBe(0); 24 | expect(queue.dequeue()).toBe(undefined); 25 | queue.enqueue(2); 26 | queue.enqueue(3); 27 | }); 28 | // 2 < 3 29 | 30 | test("Testing peek method of queue", () => { 31 | expect(queue.peek()).toBe(2); 32 | queue.dequeue(); 33 | queue.dequeue(); 34 | expect(queue.peek()).toBe(undefined); 35 | }); 36 | // 37 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/tests/SinglyLinkedList.test.js: -------------------------------------------------------------------------------- 1 | const SinglyLinkedList = require("../SinglyLinkedList"); 2 | 3 | const list = new SinglyLinkedList(); 4 | 5 | test("Testing inialization of a singly linked list", () => { 6 | expect(list.length).toBe(0); 7 | expect(list.head).toBe(undefined); 8 | expect(list.tail).toBe(undefined); 9 | }); 10 | 11 | test("Testing push method of singly linked list", () => { 12 | expect(list.push(1)).toBe(list); 13 | expect(list.length).toBe(1); 14 | expect(list.get(0)).toBe(1); 15 | list.push(32); 16 | expect(list.get(1)).toBe(32); 17 | }); 18 | // 1 > 32 19 | 20 | test("Testing pop method of singly linked list", () => { 21 | const popedNode = list.pop(); 22 | expect(popedNode.value).toBe(32); 23 | expect(popedNode.next).toBe(null); 24 | list.pop(); 25 | expect(list.length).toBe(0); 26 | expect(list.pop()).toBe(undefined); 27 | list.push(23); 28 | list.push(3); 29 | list.push(2); 30 | expect(list.pop().value).toBe(2); 31 | expect(list.length).toBe(2); 32 | }); 33 | // 23 > 3 34 | 35 | test("Testing shift method of singly linked list", () => { 36 | const shiftedNode = list.shift(); 37 | expect(shiftedNode.value).toBe(23); 38 | expect(shiftedNode.next).toBe(null); 39 | expect(list.shift().value).toBe(3); 40 | expect(list.length).toBe(0); 41 | expect(list.shift()).toBe(undefined); 42 | }); 43 | // null 44 | 45 | test("Testing unshift method of singly linked list", () => { 46 | expect(list.unshift(45)).toBe(list); 47 | expect(list.get(0)).toBe(45); 48 | expect(list.unshift(2)).toBe(list); 49 | expect(list.get(0)).toBe(2); 50 | expect(list.length).toBe(2); 51 | }); 52 | // 2 > 45 53 | 54 | test("Testing get method of singly linked list", () => { 55 | expect(list.get(-2)).toBe(undefined); 56 | expect(list.get(200)).toBe(undefined); 57 | expect(list.get(2)).toBe(undefined); 58 | expect(list.get(0)).toBe(2); 59 | expect(list.get(1)).toBe(45); 60 | }); 61 | // 2 > 45 62 | 63 | test("Testing set method of singly linked list", () => { 64 | expect(list.set(2, 100)).toBe(undefined); 65 | expect(list.set(0, 34)).toBe(true); 66 | expect(list.get(0)).toBe(34); 67 | expect(list.set(1, 25)).toBe(true); 68 | expect(list.get(1)).toBe(25); 69 | }); 70 | // 34 > 25 71 | 72 | test("Testing insert method of singly linked list", () => { 73 | expect(list.insert(0, 19)).toBe(true); 74 | expect(list.get(0)).toBe(19); 75 | expect(list.length).toBe(3); 76 | expect(list.insert(3, 20)).toBe(undefined); 77 | expect(list.insert(2, 20)).toBe(true); 78 | expect(list.get(2)).toBe(20); 79 | expect(list.length).toBe(4); 80 | }); 81 | // 19 > 34 > 20 > 25 82 | 83 | test("Testing remove method of singly linked list", () => { 84 | expect(list.remove(0)).toBe(true); 85 | expect(list.get(0)).toBe(34); 86 | expect(list.length).toBe(3); 87 | expect(list.remove(3)).toBe(undefined); 88 | expect(list.remove(2)).toBe(true); 89 | expect(list.length).toBe(2); 90 | expect(list.get(1)).toBe(20); 91 | expect(list.remove(1)).toBe(true); 92 | list.pop(); 93 | expect(list.length).toBe(0); 94 | }); 95 | // 34 96 | 97 | test("Testing reverse method of singly linked list", () => { 98 | expect(list.push(1)).toBe(list); 99 | expect(list.push(2)).toBe(list); 100 | expect(list.push(3)).toBe(list); 101 | expect(list.get(0)).toBe(1); 102 | expect(list.get(1)).toBe(2); 103 | expect(list.get(2)).toBe(3); 104 | expect(list.reverse()).toBe(list); 105 | expect(list.get(0)).toBe(3); 106 | expect(list.get(1)).toBe(2); 107 | expect(list.get(2)).toBe(1); 108 | }); 109 | // empty 110 | -------------------------------------------------------------------------------- /Data Structures/JavaScript/tests/Stack.test.js: -------------------------------------------------------------------------------- 1 | const Stack = require("../Stack"); 2 | 3 | const stack = new Stack(); 4 | 5 | test("Testing initalization of the stack", () => { 6 | expect(stack.size).toBe(0); 7 | }); 8 | 9 | test("Testing push method of the stack", () => { 10 | stack.push(1); 11 | stack.push(10); 12 | stack.push(28); 13 | expect(stack.size).toBe(3); 14 | }); 15 | // 1 > 10 > 28 16 | 17 | test("Testing pop method of the stack", () => { 18 | stack.pop(); 19 | expect(stack.size).toBe(2); 20 | expect(stack.pop()).toBe(10); 21 | stack.pop(); 22 | expect(stack.size).toBe(0); 23 | expect(stack.pop()).toBe(undefined); 24 | stack.push(120); 25 | stack.push(100); 26 | expect(stack.size).toBe(2); 27 | }); 28 | // 120 > 100 29 | 30 | test("Testing peek method of the stack", () => { 31 | expect(stack.peek()).toBe(100); 32 | stack.pop(); 33 | expect(stack.peek()).toBe(120); 34 | expect(stack.size).toBe(1); 35 | stack.pop(); 36 | expect(stack.size).toBe(0); 37 | expect(stack.peek()).toBe(undefined); 38 | }); 39 | // 40 | -------------------------------------------------------------------------------- /Disjoint Sets/QuickFind.js: -------------------------------------------------------------------------------- 1 | const _find = new WeakMap(); 2 | const _N = new WeakMap(); 3 | const _arr = new WeakMap(); 4 | 5 | class QuickFind { 6 | constructor(n) { 7 | if (n == undefined) throw new Error("Constructor parameter not passed"); 8 | 9 | _arr.set(this, []); 10 | const arr = _arr.get(this); 11 | _N.set(this, n); 12 | for (let i = 0; i <= n; i++) arr[i] = i; 13 | 14 | _find.set(this, (node) => _arr.get(this)[node]); 15 | } 16 | 17 | union(a, b) { 18 | const arr = _arr.get(this); 19 | const find = _find.get(this); 20 | const N = _N.get(this); 21 | 22 | const IDa = find(a); 23 | const IDb = find(b); 24 | 25 | if (IDa != IDb) { 26 | for (let i = 0; i < arr.length; i++) { 27 | if (arr[i] == IDa) arr[i] = IDb; 28 | } 29 | _N.set(this, N - 1); 30 | } 31 | } 32 | 33 | isConnected(a, b) { 34 | const arr = _arr.get(this); 35 | return arr[a] == arr[b]; 36 | } 37 | 38 | get count() { 39 | return _N.get(this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Disjoint Sets/QuickUnion.js: -------------------------------------------------------------------------------- 1 | const _find = new WeakMap(); 2 | const _N = new WeakMap(); 3 | const _arr = new WeakMap(); 4 | 5 | class QuickUnion { 6 | constructor(n) { 7 | if (n == undefined) throw new Error("Constructor parameter not passed"); 8 | 9 | _arr.set(this, []); 10 | const arr = _arr.get(this); 11 | _N.set(this, n); 12 | for (let i = 0; i <= n; i++) arr[i] = i; 13 | 14 | _find.set(this, (node) => { 15 | while (arr[node] != node) { 16 | node = arr[node]; 17 | } 18 | return node; 19 | }); 20 | } 21 | 22 | union(a, b) { 23 | const arr = _arr.get(this); 24 | const find = _find.get(this); 25 | const N = _N.get(this); 26 | 27 | a = find(a); 28 | b = find(b); 29 | if (a != b) { 30 | arr[a] = b; 31 | } 32 | _N.set(this, N - 1); 33 | } 34 | 35 | isConnected(a, b) { 36 | const find = _find.get(this); 37 | return find(a) == find(b); 38 | } 39 | 40 | get count() { 41 | return _N.get(this); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Disjoint Sets/QuickUnionWithPathCompression.js: -------------------------------------------------------------------------------- 1 | class QuickUnionWithPathCompression { 2 | constructor(n) { 3 | if (n == undefined) throw new Error("Constructor parameter not passed"); 4 | 5 | _arr.set(this, []); 6 | let arr = _arr.get(this); 7 | _N.set(this, n); 8 | for (let i = 0; i <= n; i++) arr[i] = i; 9 | 10 | _find.set(this, (node) => { 11 | let parentNode = node; 12 | while (arr[parentNode] != parentNode) { 13 | parentNode = arr[parentNode]; 14 | } 15 | while (arr[node] != node) { 16 | let temp = node; 17 | node = arr[node]; 18 | arr[temp] = parentNode; 19 | } 20 | return parentNode; 21 | }); 22 | } 23 | 24 | union(a, b) { 25 | let arr = _arr.get(this); 26 | let find = _find.get(this); 27 | let N = _N.get(this); 28 | 29 | a = find(a); 30 | b = find(b); 31 | if (a != b) { 32 | arr[a] = b; 33 | } 34 | _N.set(this, N - 1); 35 | } 36 | 37 | isConnected(a, b) { 38 | let find = _find.get(this); 39 | return find(a) == find(b); 40 | } 41 | 42 | get count() { 43 | return _N.get(this); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Disjoint Sets/WeightedQuickUnion.js: -------------------------------------------------------------------------------- 1 | const _find = new WeakMap(); 2 | const _N = new WeakMap(); 3 | const _arr = new WeakMap(); 4 | 5 | class WeightedQuickUnion { 6 | constructor(n) { 7 | if (n == undefined) throw new Error("Constructor parameter not passed"); 8 | 9 | _arr.set(this, []); 10 | const arr = _arr.get(this); 11 | _N.set(this, n); 12 | for (let i = 0; i <= n; i++) arr[i] = -1; 13 | this.count = 0; 14 | 15 | _find.set(this, (node) => { 16 | while (arr[node] >= 0) { 17 | node = arr[node]; 18 | this.count += 2; 19 | } 20 | this.count++; 21 | return node; 22 | }); 23 | } 24 | 25 | union(a, b) { 26 | const arr = _arr.get(this); 27 | const find = _find.get(this); 28 | const N = _N.get(this); 29 | this.count = 0; 30 | 31 | a = find(a); 32 | b = find(b); 33 | if (a != b) { 34 | if (-1 * arr[a] > -1 * arr[b]) { 35 | arr[a] += arr[b]; 36 | arr[b] = a; 37 | } else { 38 | arr[b] += arr[a]; 39 | arr[a] = b; 40 | } 41 | this.count += 6; 42 | } 43 | _N.set(this, N - 1); 44 | console.log(arr); 45 | console.log(this.count); 46 | } 47 | 48 | isConnected(a, b) { 49 | const find = _find.get(this); 50 | return find(a) == find(b); 51 | } 52 | 53 | get count1() { 54 | return _N.get(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /LinkedList/DeleteNodeInALinkedList.java: -------------------------------------------------------------------------------- 1 | // 237. Delete Node in a Linked List 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public void deleteNode(ListNode node) { 7 | ListNode lastNode = node; 8 | ListNode currentNode = node; 9 | while (currentNode.next) { 10 | currentNode.value = currentNode.next.value; 11 | lastNode = currentNode; 12 | currentNode = currentNode.next; 13 | } 14 | lastNode.next = null; 15 | } 16 | -------------------------------------------------------------------------------- /LinkedList/DeleteNodeInALinkedList.js: -------------------------------------------------------------------------------- 1 | // 237. Delete Node in a Linked List 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var deleteNode = function (node) { 7 | let lastNode = node; 8 | let currentNode = node; 9 | while (currentNode.next) { 10 | currentNode.value = currentNode.next.value; 11 | lastNode = currentNode; 12 | currentNode = currentNode.next; 13 | } 14 | lastNode.next = null; 15 | }; 16 | -------------------------------------------------------------------------------- /LinkedList/MergeTwoSortedLists.java: -------------------------------------------------------------------------------- 1 | // 21. Merge Two Sorted Lists 2 | 3 | // Time Complexity O(n + m) 4 | // Space Complexity O(1) 5 | 6 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 7 | if (l1 == null || l2 == null) { 8 | if (l1 == null && l2 != null) { 9 | return l2; 10 | } else if (l1 != null && l2 == null) { 11 | return l1; 12 | } else { 13 | return null; 14 | } 15 | } 16 | 17 | ListNode mergedListHead; 18 | ListNode node; 19 | 20 | if (l1.val < l2.val) { 21 | mergedListHead = l1; 22 | node = l1; 23 | l1 = l1.next; 24 | } else { 25 | mergedListHead = l2; 26 | node = l2; 27 | l2 = l2.next; 28 | } 29 | 30 | while (l1 != null && l2 != null) { 31 | if (l1.val < l2.val) { 32 | node.next = l1; 33 | l1 = l1.next; 34 | } else { 35 | node.next = l2; 36 | l2 = l2.next; 37 | } 38 | node = node.next; 39 | } 40 | 41 | if (l1 == null) { 42 | node.next = l2; 43 | } else { 44 | node.next = l1; 45 | } 46 | return mergedListHead; 47 | } 48 | 49 | // Cleaner solution 50 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 51 | ListNode mergedListHead = new ListNode(0, null); 52 | ListNode node = mergedListHead; 53 | 54 | while (l1 != null && l2 != null) { 55 | if (l1.val < l2.val) { 56 | node.next = l1; 57 | l1 = l1.next; 58 | } else { 59 | node.next = l2; 60 | l2 = l2.next; 61 | } 62 | node = node.next; 63 | } 64 | if (l1 == null) { 65 | node.next = l2; 66 | } else if (l2 == null){ 67 | node.next = l1; 68 | } 69 | return mergedListHead.next; 70 | } 71 | -------------------------------------------------------------------------------- /LinkedList/MergeTwoSortedLists.js: -------------------------------------------------------------------------------- 1 | // 21. Merge Two Sorted Lists 2 | 3 | // Time Complexity O(n + m) 4 | // Space Complexity O(1) 5 | 6 | var mergeTwoLists = function (l1, l2) { 7 | if (l1 === null || l2 === null) { 8 | if (l1 === null && l2 !== null) { 9 | return l2; 10 | } else if (l1 !== null && l2 === null) { 11 | return l1; 12 | } else { 13 | return null; 14 | } 15 | } 16 | 17 | let mergedListHead; 18 | let node; 19 | 20 | if (l1.val < l2.val) { 21 | mergedListHead = l1; 22 | node = l1; 23 | l1 = l1.next; 24 | } else { 25 | mergedListHead = l2; 26 | node = l2; 27 | l2 = l2.next; 28 | } 29 | 30 | while (l1 !== null && l2 !== null) { 31 | if (l1.val < l2.val) { 32 | node.next = l1; 33 | l1 = l1.next; 34 | } else { 35 | node.next = l2; 36 | l2 = l2.next; 37 | } 38 | node = node.next; 39 | } 40 | 41 | if (l1 === null) { 42 | node.next = l2; 43 | } else { 44 | node.next = l1; 45 | } 46 | return mergedListHead; 47 | }; 48 | 49 | // Cleaner version 50 | const mergedListHead = new ListNode(null, null); 51 | let node = mergedListHead; 52 | 53 | while (l1 && l2) { 54 | if (l1.val < l2.val) { 55 | node.next = l1; 56 | l1 = l1.next; 57 | } else { 58 | node.next = l2; 59 | l2 = l2.next; 60 | } 61 | node = node.next; 62 | } 63 | node.next = l1 || l2; 64 | 65 | return mergedListHead.next; 66 | }; 67 | -------------------------------------------------------------------------------- /LinkedList/PalindromeLinkedList.js: -------------------------------------------------------------------------------- 1 | // 234. Palindrome Linked List 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | var isPalindrome = function (head) { 7 | let node = head; 8 | let length = 1; 9 | 10 | while (node.next) { 11 | length++; 12 | node = node.next; 13 | } 14 | 15 | if (length === 1) { 16 | return true; 17 | } 18 | 19 | 20 | let mid = length; 21 | let midNode = head; 22 | while (mid !== Math.ceil(length / 2)) { 23 | midNode = midNode.next; 24 | mid--; 25 | } 26 | 27 | const rightHalf = []; 28 | while (midNode) { 29 | rightHalf.push(midNode.val); 30 | midNode = midNode.next; 31 | } 32 | 33 | node = head; 34 | while (rightHalf.length) { 35 | if (rightHalf.pop() !== node.val) { 36 | return false; 37 | } 38 | node = node.next; 39 | } 40 | 41 | return true; 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /Miscellaneous/HigherOrderMethods.js: -------------------------------------------------------------------------------- 1 | const _ = {}; 2 | 3 | _.isObject = function (obj) { 4 | return Object.prototype.toString.call(obj) === "[object Object]"; 5 | }; 6 | 7 | _.forEach = function (list, callback) { 8 | if (Array.isArray(list)) { 9 | for (let i = 0; i < list.length; i++) { 10 | callback(list[i], i, list); 11 | } 12 | } 13 | if (_.isObject(list)) { 14 | let keys = Object.keys(list); 15 | for (let i = 0; i < keys.length; i++) { 16 | callback(list[keys[i]], keys[i], list); 17 | } 18 | } 19 | }; 20 | 21 | _.map = function (list, callback) { 22 | if (!Array.isArray(list)) { 23 | throw new Error("The first parameter is not an Array"); 24 | } 25 | const newArray = []; 26 | for (let i = 0; i < list.length; i++) { 27 | newArray.push(callback(list[i], i, list)); 28 | } 29 | return newArray; 30 | }; 31 | 32 | _.filter = function (list, callback) { 33 | if (!Array.isArray(list)) { 34 | throw new Error("The first parameter is not an Array"); 35 | } 36 | const newArray = []; 37 | for (let i = 0; i < list.length; i++) { 38 | let val = callback(list[i], i, list); 39 | if (val) newArray.push(list[i]); 40 | } 41 | return newArray; 42 | }; 43 | 44 | _.reduce = function (list, callback, initial = 0) { 45 | let accum = initial; 46 | if (!Array.isArray(list)) { 47 | throw new Error("The first parameter is not an Array"); 48 | } 49 | for (let i = 0; i < list.length; i++) { 50 | accum = callback(accum, list[i], i); 51 | } 52 | return accum; 53 | }; 54 | 55 | _.some = function (list, callback) { 56 | if (!Array.isArray(list)) { 57 | throw new Error("The first parameter is not an Array"); 58 | } 59 | for (let i = 0; i < list.length; i++) { 60 | if (callback(list[i], i, list)) { 61 | return true; 62 | } 63 | } 64 | }; 65 | 66 | _.every = function (list, callback) { 67 | if (!Array.isArray(list)) { 68 | throw new Error("The first parameter is not an Array"); 69 | } 70 | for (let i = 0; i < list.length; i++) { 71 | if (!callback(list[i], i, list)) { 72 | return false; 73 | } 74 | } 75 | }; 76 | 77 | _.find = function (list, callback) { 78 | if (!Array.isArray(list)) { 79 | throw new Error("The first parameter is not an Array"); 80 | } 81 | for (let i = 0; i < list.length; i++) { 82 | if (callback(list[i], i, list)) { 83 | return list[i]; 84 | } 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /Miscellaneous/Polyfills.js: -------------------------------------------------------------------------------- 1 | Array.prototype.myMap = function myMap(callback, thisArg = this) { 2 | const newArray = []; 3 | for (let i = 0; i < this.length; i++) { 4 | newArray.push(callback.call(thisArg, this[i], i, this)); 5 | } 6 | return newArray; 7 | }; 8 | 9 | Array.prototype.myFilter = function myFilter(callback, thisArg = this) { 10 | const result = []; 11 | for (let i = 0; i < this.length; i++) { 12 | if (callback.call(thisArg, this[i], i, this)) { 13 | result.push(this[i]); 14 | } 15 | } 16 | return result; 17 | }; 18 | 19 | Array.prototype.myReduce = function myReduce(callback, initialValue) { 20 | let accumulator = initialValue || this[0]; 21 | for (let i = initialValue ? 0 : 1; i < this.length; i++) { 22 | accumulator = callback(accumulator, this[i], i, this); 23 | } 24 | return accumulator; 25 | }; 26 | 27 | Array.prototype.myForEach = function myForEach(callback, thisArg = this) { 28 | for (let i = 0; i < this.length; i++) { 29 | callback.call(thisArg, this[i], i, this); 30 | } 31 | }; 32 | 33 | Function.prototype.myCall = function myCall(thisArg, ...args) { 34 | const symbol = Symbol(); 35 | thisArg[symbol] = this; 36 | const result = thisArg[symbol](...args); 37 | delete thisArg[symbol]; 38 | return result; 39 | }; 40 | 41 | Function.prototype.myApply = function myApply(thisArg, args) { 42 | const symbol = Symbol(); 43 | thisArg[symbol] = this; 44 | const result = thisArg[symbol](...args); 45 | delete thisArg[symbol]; 46 | return result; 47 | }; 48 | 49 | Function.prototype.myBind = function myBind(thisArg, ...args) { 50 | const fn = this; 51 | return function boundWrapperFunction(...args2) { 52 | fn.call(thisArg, ...args, ...args2); 53 | }; 54 | }; 55 | 56 | Promise.myAll = function myAll(promises) { 57 | const results = []; 58 | let resolvedPromises = 0; 59 | 60 | if (promises.length === 0) { 61 | return Promise.resolve(results); 62 | } 63 | 64 | return new Promise((resolve, reject) => { 65 | for (let i = 0; i < promises.length; i++) { 66 | if (promises[i]?.then) { 67 | promises[i] 68 | .then((data) => { 69 | results[i] = data; 70 | resolvedPromises++; 71 | 72 | if (resolvedPromises >= promises.length) { 73 | resolve(results); 74 | } 75 | }) 76 | .catch((err) => { 77 | reject(err); 78 | }); 79 | } else { 80 | results[i] = promises[i]; 81 | resolvedPromises++; 82 | 83 | if (resolvedPromises >= promises.length) { 84 | resolve(results); 85 | } 86 | } 87 | } 88 | }); 89 | }; 90 | 91 | Promise.myAllSettled = function myAllSettled(promises) { 92 | const results = []; 93 | let resolvedPromises = 0; 94 | 95 | if (promises.length === 0) { 96 | return Promise.resolve(results); 97 | } 98 | 99 | return new Promise((resolve, reject) => { 100 | for (let i = 0; i < promises.length; i++) { 101 | if (promises[i]?.then) { 102 | promises[i] 103 | .then((value) => { 104 | results[i] = { 105 | status: "fulfilled", 106 | value, 107 | }; 108 | }) 109 | .catch((reason) => { 110 | results[i] = { 111 | status: "rejected", 112 | reason, 113 | }; 114 | }) 115 | .finally(() => { 116 | resolvedPromises++; 117 | 118 | if (resolvedPromises >= promises.length) { 119 | resolve(results); 120 | } 121 | }); 122 | } else { 123 | Promise.resolve(promises[i]) 124 | .then((value) => { 125 | results[i] = { 126 | status: "fulfilled", 127 | value, 128 | }; 129 | }) 130 | .finally(() => { 131 | resolvedPromises++; 132 | 133 | if (resolvedPromises >= promises.length) { 134 | resolve(results); 135 | } 136 | }); 137 | } 138 | } 139 | }); 140 | }; 141 | 142 | Promise.myRace = function myRace(promises) { 143 | return new Promise((resolve, reject) => { 144 | for (const promise of promises) { 145 | if (promise?.then) { 146 | promise 147 | .then((data) => resolve(data)) 148 | .catch((error) => reject(error)); 149 | } else { 150 | Promise.resolve(promise).then((data) => resolve(data)); 151 | } 152 | } 153 | }); 154 | }; 155 | 156 | Promise.myAny = function myAny(promises) { 157 | const errors = []; 158 | let rejectedPromises = 0; 159 | 160 | return new Promise((resolve, reject) => { 161 | for (const [index, promise] of Object.entries(promises)) { 162 | if (promise?.then) { 163 | promise 164 | .then((result) => resolve(result)) 165 | .catch((error) => { 166 | errors[index] = error; 167 | rejectedPromises++; 168 | 169 | if (rejectedPromises >= promises.length) { 170 | reject(errors); 171 | } 172 | }); 173 | } else { 174 | Promise.resolve(promise).then((result) => resolve(result)); 175 | } 176 | } 177 | }); 178 | }; 179 | 180 | Promise.myResolve = function myResolve(value) { 181 | return new Promise((resolve) => resolve(value)); 182 | }; 183 | 184 | Promise.myReject = function myReject(value) { 185 | return new Promise((_, reject) => reject(value)); 186 | }; 187 | -------------------------------------------------------------------------------- /Miscellaneous/Utils.js: -------------------------------------------------------------------------------- 1 | function memoize(func) { 2 | const cache = {}; 3 | return function memoizedFunction(...args) { 4 | const stringifiedArgs = JSON.stringify(args); 5 | if (cache[stringifiedArgs]) { 6 | return cache[stringifiedArgs]; 7 | } 8 | const result = func(...args); 9 | cache[stringifiedArgs] = result; 10 | return result; 11 | }; 12 | } 13 | 14 | function flattenArray(array) { 15 | const newArray = []; 16 | for (const element of array) { 17 | if (Array.isArray(element)) { 18 | newArray.push(...flattenArray(element)); 19 | } else { 20 | newArray.push(element); 21 | } 22 | } 23 | 24 | return newArray; 25 | } 26 | -------------------------------------------------------------------------------- /Pattern Problems/Chessboard.js: -------------------------------------------------------------------------------- 1 | /* 2 | # # # # 3 | # # # # 4 | # # # # 5 | # # # # 6 | # # # # 7 | # # # # 8 | # # # # 9 | # # # # 10 | */ 11 | 12 | function chessboard(n) { 13 | for (let i = 0; i < n; i++) { 14 | for (let j = 0; j < n; j++) { 15 | if (i % 2 == 0 && j % 2 != 0) 16 | process.stdout.write(" " + "#"); 17 | if (i % 2 != 0 && j % 2 == 0) 18 | process.stdout.write("#" + " "); 19 | } 20 | console.log(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Pattern Problems/Triangle.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * * 4 | * * * 5 | * * * * 6 | * * * * * 7 | */ 8 | 9 | function pattern(n) { 10 | for (let i = 0; i < n; i++) { 11 | for (let j = 0; j <= i; j++) { 12 | process.stdout.write("*" + " "); 13 | } 14 | console.log(); 15 | } 16 | } 17 | 18 | /* 19 | * * * * * * * 20 | * * * * * * 21 | * * * * * 22 | * * * * 23 | * * * 24 | * * 25 | * 26 | */ 27 | 28 | function pattern(n) { 29 | for (let i = n; i > 0; i--) { 30 | for (let j = 0; j < i; j++) { 31 | process.stdout.write("*" + " "); 32 | } 33 | console.log(); 34 | } 35 | } 36 | 37 | /* 38 | * 39 | ** 40 | *** 41 | **** 42 | ***** 43 | */ 44 | 45 | function pattern(n) { 46 | for (let i = n; i > 0; i--) { 47 | for (let j = 0; j < i - 1; j++) { 48 | process.stdout.write(" "); 49 | } 50 | for (let j = 0; j <= n - i; j++) { 51 | process.stdout.write("*"); 52 | } 53 | console.log(); 54 | } 55 | } 56 | 57 | /* 58 | * 59 | * * 60 | * * * 61 | * * * * 62 | * * * * * 63 | */ 64 | 65 | function pattern(n) { 66 | for (let i = n; i > 0; i--) { 67 | for (let j = 0; j < i - 1; j++) { 68 | process.stdout.write(" "); 69 | } 70 | for (let j = 0; j <= n - i; j++) { 71 | process.stdout.write("*" + " "); // just add space in the above program 72 | } 73 | console.log(); 74 | } 75 | } 76 | 77 | /* 78 | ***** 79 | **** 80 | *** 81 | ** 82 | * 83 | */ 84 | 85 | function pattern(n) { 86 | for (let i = n; i > 0; i--) { 87 | for (let j = 0; j < n - i; j++) { 88 | process.stdout.write(" "); 89 | } 90 | for (let j = 0; j < i; j++) { 91 | process.stdout.write("*"); 92 | } 93 | console.log(); 94 | } 95 | } 96 | 97 | /* 98 | * * * * * 99 | * * * * 100 | * * * 101 | * * 102 | * 103 | */ 104 | 105 | function pattern(n) { 106 | for (let i = n; i > 0; i--) { 107 | for (let j = 0; j < n - i; j++) { 108 | process.stdout.write(" "); 109 | } 110 | for (let j = 0; j < i; j++) { 111 | process.stdout.write("*" + " "); // just add space in the above program 112 | } 113 | console.log(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Order that can be followed 2 | - [Basic Problems](https://github.com/RohitDhatrak/DS-Algo/tree/main/BasicProblems) 3 | - [Arrays](https://github.com/RohitDhatrak/DS-Algo/tree/main/Arrays) 4 | - [2D Arrays](https://github.com/RohitDhatrak/DS-Algo/tree/main/2dArray) 5 | 6 | ### Connect With Me 7 | - Twitter – [@rohit_dhatrak_](https://twitter.com/rohit_dhatrak_) 8 | - LinkedIn – [/rohitdhatrak](https://www.linkedin.com/in/rohitdhatrak) 9 | - Other Links – [/rohitdhatrak](https://rohitdhatrak.bio.link/) 10 | -------------------------------------------------------------------------------- /Recursion/CapitalizeFirst.js: -------------------------------------------------------------------------------- 1 | // Write a function that capitalizes the first letter of every word in an Array 2 | 3 | function capitalizeFirst(arr) { 4 | function capitalize(element) { 5 | return element[0].toUpperCase() + element.slice(1); 6 | } 7 | 8 | if (!arr.length) { 9 | return []; 10 | } else { 11 | return [capitalize(arr.shift()), ...capitalizeFirst(arr)]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Recursion/CollectStrings.js: -------------------------------------------------------------------------------- 1 | // Write a recursive sunciton that accepts an object and returns an array of all the strings present in the object 2 | 3 | // const obj = { 4 | // stuff: "foo", 5 | // data: { 6 | // val: { 7 | // thing: { 8 | // info: "bar", 9 | // moreInfo: { 10 | // evenMoreInfo: { 11 | // weMadeIt: "baz" 12 | // } 13 | // } 14 | // } 15 | // } 16 | // } 17 | // } 18 | 19 | // var obj1 = { 20 | // outer: 2, 21 | // obj: { 22 | // inner: 2, 23 | // otherObj: { 24 | // superInner: 2, 25 | // notANumber: true, 26 | // alsoNotANumber: "yup", 27 | // }, 28 | // }, 29 | // }; 30 | 31 | // var obj2 = { 32 | // a: 2, 33 | // b: { b: 2, bb: { b: 3, bb: { b: 2 } } }, 34 | // c: { c: { c: 2 }, cc: "ball", ccc: 5 }, 35 | // d: 1, 36 | // e: { e: { e: 2 }, ee: "car" }, 37 | // }; 38 | 39 | // collectStrings(obj) // ["foo", "bar", "baz"]) 40 | // console.log(collectStrings(obj1)); // ["yup"] 41 | // console.log(collectStrings(obj2)); // ["ball", "car"] 42 | 43 | function collectStrings(obj) { 44 | function isObject(input) { 45 | return typeof input === "object" && input !== null; 46 | } 47 | 48 | function isString(input) { 49 | return typeof input === "string"; 50 | } 51 | 52 | const keys = Object.keys(obj); 53 | if (!keys.length) { 54 | return []; 55 | } else { 56 | if (isObject(obj[keys[0]])) { 57 | const nestedObj = obj[keys[0]]; 58 | delete obj[keys[0]]; 59 | return [...collectStrings(nestedObj), ...collectStrings(obj)]; 60 | } else { 61 | const primitive = obj[keys[0]]; 62 | delete obj[keys[0]]; 63 | if (isString(primitive)) { 64 | return [primitive, ...collectStrings(obj)]; 65 | } else { 66 | return [...collectStrings(obj)]; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Recursion/EvenOdd.js: -------------------------------------------------------------------------------- 1 | function evenOdd(n) { 2 | if (n < 0) 3 | n = -n; 4 | if (n == 0) 5 | return "even"; 6 | if (n == 1) 7 | return "odd"; 8 | return 9 | evenOdd(n - 2); 10 | } 11 | -------------------------------------------------------------------------------- /Recursion/FlattenNestedArrays.js: -------------------------------------------------------------------------------- 1 | // Write a function flatten which accepts an array of arrays and returns a new array with all the values flattened. 2 | 3 | // flatten([1, 2, 3, [4, 5] ]) // [1, 2, 3, 4, 5] 4 | // flatten([1, [2, [3, 4], [[5]]]]) // [1, 2, 3, 4, 5] 5 | // flatten([[1],[2],[3]]) // [1,2,3] 6 | // flatten([[[[1], [[[2]]], [[[[[[[3]]]]]]]]]]) // [1,2,3 7 | 8 | function flatten(arr) { 9 | function isArray(element) { 10 | return Array.isArray(element); 11 | } 12 | 13 | if (!arr.length) { 14 | return []; 15 | } else { 16 | if (isArray(arr[0])) { 17 | return [...flatten(arr.shift()), ...flatten(arr)]; 18 | } else { 19 | return [arr.shift(), ...flatten(arr)]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Recursion/NestedEvenSum.js: -------------------------------------------------------------------------------- 1 | // Write a recursive function that returns the sum of all the even numbers in an object which may contain nested objects. 2 | 3 | // var obj1 = { 4 | // outer: 2, 5 | // obj: { 6 | // inner: 2, 7 | // otherObj: { 8 | // superInner: 2, 9 | // notANumber: true, 10 | // alsoNotANumber: "yup" 11 | // } 12 | // } 13 | // } 14 | 15 | // var obj2 = { 16 | // a: 2, 17 | // b: {b: 2, bb: {b: 3, bb: {b: 2}}}, 18 | // c: {c: {c: 2}, cc: 'ball', ccc: 5}, 19 | // d: 1, 20 | // e: {e: {e: 2}, ee: 'car'} 21 | // }; 22 | 23 | // nestedEvenSum(obj1); // 6 24 | // nestedEvenSum(obj2); // 10 25 | 26 | function nestedEvenSum(obj) { 27 | function isObject(input) { 28 | return typeof input === "object" && input !== null; 29 | } 30 | 31 | function isEvenNumber(input) { 32 | if (typeof input === "number") { 33 | return input % 2 === 0; 34 | } else { 35 | return false; 36 | } 37 | } 38 | 39 | const keys = Object.keys(obj); 40 | if (!keys.length) { 41 | return 0; 42 | } else { 43 | if (isObject(obj[keys[0]])) { 44 | const nestedObj = obj[keys[0]]; 45 | delete obj[keys[0]]; 46 | return nestedEvenSum(nestedObj) + nestedEvenSum(obj); 47 | } else { 48 | const primitive = obj[keys[0]]; 49 | delete obj[keys[0]]; 50 | if (isEvenNumber(primitive)) { 51 | return primitive + nestedEvenSum(obj); 52 | } else { 53 | return 0 + nestedEvenSum(obj); 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Recursion/README.md: -------------------------------------------------------------------------------- 1 | ### Good Questions 2 | 3 | - [Flatten Nested Array](https://github.com/RohitDhatrak/DS-Algo/blob/main/Recursion/FlattenNestedArrays.js) 4 | - [Nested Even Sum](https://github.com/RohitDhatrak/DS-Algo/blob/main/Recursion/NestedEvenSum.js) 5 | - [Stringify Numbers](https://github.com/RohitDhatrak/DS-Algo/tree/main/Recursion/StringifyNumbers.js) 6 | -------------------------------------------------------------------------------- /Recursion/SomeRecursive.js: -------------------------------------------------------------------------------- 1 | // Write a recursive function called someRecursive which accepts an array and a callback. 2 | // The function returns true if a single value in the array returns true when passed to the callback. Otherwise it returns false. 3 | 4 | // SAMPLE INPUT / OUTPUT 5 | // const isOdd = val => val % 2 !== 0; 6 | 7 | // someRecursive([1,2,3,4], isOdd) // true 8 | // someRecursive([4,6,8,9], isOdd) // true 9 | // someRecursive([4,6,8], isOdd) // false 10 | // someRecursive([4,6,8], val => val > 10); // false 11 | 12 | function someRecursive(arr, callback) { 13 | if (!arr.length) { 14 | return false; 15 | } else { 16 | if (callback(arr.pop())) { 17 | return true; 18 | } else { 19 | return someRecursive(arr, callback); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Recursion/StringifyNumbers.js: -------------------------------------------------------------------------------- 1 | // Write a recursive funciton that takes an object and converts all the numbers in that object into a string. 2 | 3 | // const obj = { 4 | // num: 1, 5 | // test: [], 6 | // data: { 7 | // val: 4, 8 | // info: { 9 | // isRight: true, 10 | // random: 66, 11 | // }, 12 | // }, 13 | // }; 14 | 15 | function stringifyNumbers(obj) { 16 | function isObject(input) { 17 | return ( 18 | typeof input === "object" && input !== null && !Array.isArray(input) 19 | ); 20 | } 21 | 22 | function isNumber(input) { 23 | return typeof input === "number"; 24 | } 25 | 26 | const keys = Object.keys(obj); 27 | if (!keys.length) { 28 | return {}; 29 | } else { 30 | if (isObject(obj[keys[0]])) { 31 | const key = keys[0]; 32 | const nestedObj = obj[keys[0]]; 33 | delete obj[keys[0]]; 34 | return { 35 | [key]: stringifyNumbers(nestedObj), 36 | ...stringifyNumbers(obj), 37 | }; 38 | } else { 39 | const key = keys[0]; 40 | const primitive = obj[keys[0]]; 41 | delete obj[keys[0]]; 42 | if (isNumber(primitive)) { 43 | return { [key]: primitive + "", ...stringifyNumbers(obj) }; 44 | } else { 45 | return { [key]: primitive, ...stringifyNumbers(obj) }; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Searching/BinarySearch.js: -------------------------------------------------------------------------------- 1 | // Time Complexity O(logn) 2 | // Space Complexity O(1) 3 | 4 | var binarySearch = function (nums, target) { 5 | let start = 0; 6 | let end = nums.length - 1; 7 | 8 | while (start <= end) { 9 | let mid = Math.round((start + end) / 2); 10 | if (nums[mid] === target) { 11 | return mid; 12 | } else if (nums[mid] < target) { 13 | start = mid + 1; 14 | } else { 15 | end = mid - 1; 16 | } 17 | } 18 | return -1; 19 | }; 20 | -------------------------------------------------------------------------------- /Searching/FindSmallestLetterGreaterThanTarget.js: -------------------------------------------------------------------------------- 1 | // 744. Find Smallest Letter Greater Than Target 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | var nextGreatestLetter = function(letters, target) { 7 | let start = 0; 8 | let end = letters.length - 1; 9 | while(start <= end){ 10 | let mid = Math.trunc((start + end) / 2); 11 | if (target >= letters[mid]){ 12 | start = mid + 1; 13 | }else{ 14 | end = mid - 1; 15 | } 16 | } 17 | return letters[start % letters.length]; 18 | }; 19 | -------------------------------------------------------------------------------- /Searching/FirstBadVersion.java: -------------------------------------------------------------------------------- 1 | // 278. First Bad Version 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | public int firstBadVersion(int n) { 7 | int start = 1; 8 | int end = n; 9 | 10 | while (start <= end) { // = is necessary 11 | int mid = start + (end - start) / 2; // Overflow issues 12 | if (isBadVersion(mid)) { 13 | end = mid - 1; 14 | } else { 15 | start = mid + 1; 16 | } 17 | } 18 | 19 | return end + 1; // or return start; 20 | } 21 | -------------------------------------------------------------------------------- /Searching/FirstBadVersion.js: -------------------------------------------------------------------------------- 1 | // 278. First Bad Version 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | var solution = function(isBadVersion) { 7 | /** 8 | * @param {integer} n Total versions 9 | * @return {integer} The first bad version 10 | */ 11 | return function(n) { 12 | let start = 1; 13 | let end = n; 14 | 15 | while (start <= end) { // = is necessary 16 | const mid = Math.floor((start + end) / 2); 17 | if (isBadVersion(mid)) { 18 | end = mid - 1; 19 | } else { 20 | start = mid + 1; 21 | } 22 | } 23 | 24 | return end + 1; // or return start; 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /Searching/IntersectionOfTwoArrays.java: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // assuming arrays are sorted 4 | // Solution 1: using binary search 5 | // Time Complextiy O(nlogm) 6 | // Space Complexity O(1) 7 | 8 | class Solution { 9 | public int[] intersection(int[] nums1, int[] nums2) { 10 | Arrays.sort(nums1); 11 | Arrays.sort(nums2); 12 | 13 | int[] smaller = nums1.length <= nums2.length ? nums1 : nums2; 14 | int[] larger = nums1.length > nums2.length ? nums1 : nums2; 15 | int lastNum = -1; 16 | 17 | ArrayList list = new ArrayList(); 18 | 19 | for (int num: smaller) { 20 | if (num != lastNum && binarySearch(larger, num) ) { 21 | list.add(num); 22 | } 23 | lastNum = num; 24 | } 25 | 26 | int[] ans = new int[list.size()]; 27 | for (int i = 0; i < list.size(); i++) { 28 | ans[i] = list.get(i); 29 | } 30 | 31 | return ans; 32 | } 33 | 34 | public boolean binarySearch(int[] nums, int target) { 35 | int start = 0; 36 | int end = nums.length - 1; 37 | 38 | while (start <= end) { 39 | int mid = (start + end) / 2; 40 | if (nums[mid] == target) { 41 | return true; 42 | } else if (nums[mid] < target) { 43 | start = mid + 1; 44 | } else { 45 | end = mid - 1; 46 | } 47 | } 48 | return false; 49 | 50 | } 51 | } 52 | 53 | // Solution 2: in arrays folder 54 | // Solution 3: in 2 pointer folder 55 | -------------------------------------------------------------------------------- /Searching/IntersectionOfTwoArrays.js: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // assuming arrays are sorted 4 | // Solution 1: using binary search 5 | // Time Complextiy O(nlogm) 6 | // Space Complexity O(1) 7 | 8 | var intersection = function(nums1, nums2) { 9 | nums1 = nums1.sort((a, b) => a - b); 10 | nums2 = nums2.sort((a, b) => a - b); 11 | 12 | const smaller = nums1.length <= nums2.length ? nums1 : nums2; 13 | const larger = nums1.length > nums2.length ? nums1 : nums2; 14 | let lastNum = -1; 15 | const ans = []; 16 | 17 | for (const num of smaller) { 18 | if (num !== lastNum && binarySearch(larger, num)) { 19 | ans.push(num); 20 | } 21 | lastNum = num; 22 | } 23 | return ans; 24 | }; 25 | 26 | function binarySearch(nums, target) { 27 | let start = 0; 28 | let end = nums.length - 1; 29 | 30 | while (start <= end) { 31 | let mid = Math.round((start + end) / 2); 32 | if (nums[mid] === target) { 33 | return true; 34 | } else if (nums[mid] < target) { 35 | start = mid + 1; 36 | } else { 37 | end = mid - 1; 38 | } 39 | } 40 | return false 41 | }; 42 | 43 | // Solution 2: in arrays folder 44 | // Solution 3: in 2 pointer folder 45 | -------------------------------------------------------------------------------- /Searching/LinearSearch.js: -------------------------------------------------------------------------------- 1 | // We compare each element in the array with the key 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | function linearSearch(arr, key) { 7 | for (let i = 0; i < arr.length; i++) 8 | if (arr[i] == key) 9 | return i; 10 | return -1; 11 | } 12 | -------------------------------------------------------------------------------- /Searching/PeakIndexInAMountainArray.js: -------------------------------------------------------------------------------- 1 | // 852. Peak Index in a Mountain Array 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | var peakIndexInMountainArray = function(arr) { 7 | let lhs = 0; 8 | let rhs = arr.length - 1; 9 | while(lhs <= rhs){ 10 | const middle = Math.trunc((lhs + rhs) / 2); 11 | if(arr[middle + 1] < arr[middle] && arr[middle - 1] < arr[middle]){ 12 | return middle; 13 | }else if (arr[middle + 1] > arr[middle]){ 14 | lhs = middle + 1; 15 | }else{ 16 | rhs = middle - 1; 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Searching/README.md: -------------------------------------------------------------------------------- 1 | [First Bad Version (checkout the diff btw java and javascript version)](https://github.com/RohitDhatrak/DS-Algo/blob/main/Searching/FirstBadVersion.java) 2 | -------------------------------------------------------------------------------- /Searching/SearchInsertPosition.java: -------------------------------------------------------------------------------- 1 | // 35. Search Insert Position 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | public int searchInsert(int[] nums, int target) { 7 | int start = 0; 8 | int end = nums.length - 1; 9 | 10 | while (start <= end) { // = is necessary 11 | int mid = (start + end) / 2; 12 | if (nums[mid] == target) { 13 | return mid; 14 | } else if (nums[mid] > target) { 15 | end = mid - 1; 16 | } else { 17 | start = mid + 1; 18 | } 19 | } 20 | return end+1; // or return start; 21 | } 22 | -------------------------------------------------------------------------------- /Searching/SearchInsertPosition.js: -------------------------------------------------------------------------------- 1 | // 35. Search Insert Position 2 | 3 | // Time Complexity O(logn) 4 | // Space Complexity O(1) 5 | 6 | var searchInsert = function(nums, target) { 7 | let start = 0; 8 | let end = nums.length - 1; 9 | 10 | while (start <= end) { // = is necessary 11 | const mid = Math.floor((start + end) / 2); 12 | if (nums[mid] === target) { 13 | return mid; 14 | } else if (nums[mid] > target) { 15 | end = mid - 1; 16 | } else { 17 | start = mid + 1; 18 | } 19 | } 20 | return end+1; // or return start; 21 | }; 22 | -------------------------------------------------------------------------------- /Sliding Window/FindAllAnagramsInAString.java: -------------------------------------------------------------------------------- 1 | // 438. Find All Anagrams in a String 2 | 3 | // Time Complexity O(n) 4 | // Space Complextiy O(n) 5 | 6 | class Solution { 7 | int counter; 8 | 9 | public void addCharAndDecrementCounter(char character, HashMap map) { 10 | map.put(character, map.get(character) - 1); 11 | if (map.get(character) >= 0) { 12 | counter--; 13 | } 14 | } 15 | 16 | public void removeCharAndIncrementCounter(char character, HashMap map) { 17 | map.put(character, map.get(character) + 1); 18 | if (map.get(character) > 0) { 19 | counter++; 20 | } 21 | } 22 | 23 | public void checkIfCharIsPartOfP(char character, boolean isBeingAdded, HashMap map) { 24 | if (map.containsKey(character)) { 25 | if (isBeingAdded) { 26 | addCharAndDecrementCounter(character, map); 27 | } else { 28 | removeCharAndIncrementCounter(character, map); 29 | } 30 | } 31 | } 32 | 33 | public List findAnagrams(String s, String p) { 34 | ArrayList ans = new ArrayList<>(); 35 | if (p.length() > s.length()) { 36 | return ans; 37 | } 38 | counter = p.length(); 39 | int begin = 0; 40 | int end = p.length(); 41 | HashMap map = new HashMap<>(); 42 | 43 | for (int i = 0; i < p.length(); i++) { 44 | char character = p.charAt(i); 45 | if (map.containsKey(character )) { 46 | map.put(character , map.get(character ) + 1); 47 | } else { 48 | map.put(character , 1); 49 | } 50 | } 51 | 52 | for (int i = 0; i < end; i++) { 53 | checkIfCharIsPartOfP(s.charAt(i), true, map); 54 | } 55 | 56 | while (end <= s.length()) { 57 | if (counter == 0) { 58 | ans.add(begin); 59 | } 60 | 61 | char startChar = s.charAt(begin); 62 | checkIfCharIsPartOfP(startChar, false, map); 63 | 64 | if (end < s.length()) { 65 | char endChar = s.charAt(end); 66 | checkIfCharIsPartOfP(endChar, true, map); 67 | } 68 | 69 | begin++; 70 | end++; 71 | } 72 | 73 | return ans; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Sliding Window/FindAllAnagramsInAString.js: -------------------------------------------------------------------------------- 1 | // 438. Find All Anagrams in a String 2 | 3 | // Time Complexity O(n) 4 | // Space Complextiy O(n) 5 | 6 | var findAnagrams = function(s, p) { 7 | const map = new Map(); 8 | let counter = p.length; 9 | let begin = 0; 10 | let end = p.length; 11 | const ans = []; 12 | 13 | function addCharAndDecrementCounter(character) { 14 | map.set(character, map.get(character) - 1); 15 | if (map.get(character) >= 0) { 16 | counter--; 17 | } 18 | } 19 | 20 | function removeCharAndIncrementCounter(character) { 21 | map.set(character, map.get(character) + 1); 22 | if (map.get(character) > 0) { 23 | counter++; 24 | } 25 | } 26 | 27 | function checkIfCharIsPartOfP(character, isBeingAdded) { 28 | if (map.has(character)) { 29 | if (isBeingAdded) { 30 | addCharAndDecrementCounter(character); 31 | } else { 32 | removeCharAndIncrementCounter(character); 33 | } 34 | } 35 | } 36 | 37 | for (let char of p) { 38 | if (map.has(char)) { 39 | map.set(char, map.get(char) + 1); 40 | } else { 41 | map.set(char, 1); 42 | } 43 | } 44 | 45 | for (let i = 0; i < end; i++) { 46 | checkIfCharIsPartOfP(s[i], true); 47 | } 48 | 49 | while (end <= s.length) { 50 | if (counter === 0) { 51 | ans.push(begin); 52 | } 53 | 54 | const startChar = s[begin]; 55 | const endChar = s[end]; 56 | 57 | checkIfCharIsPartOfP(startChar, false); 58 | checkIfCharIsPartOfP(endChar, true); 59 | 60 | begin++; 61 | end++; 62 | } 63 | 64 | return ans; 65 | }; 66 | -------------------------------------------------------------------------------- /Sliding Window/FruitIntoBaskets.java: -------------------------------------------------------------------------------- 1 | // 904. Fruit Into Baskets 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | public int totalFruit(int[] fruits) { 7 | int startPoint = 0; 8 | int endPoint = 0; 9 | HashMap fruitBucket = new HashMap<>(); 10 | int currentCount = 0; 11 | int maxCount = 0; 12 | 13 | while (startPoint < fruits.length && endPoint < fruits.length) { 14 | int fruit = fruits[endPoint]; 15 | if (fruitBucket.containsKey(fruit)) { 16 | fruitBucket.put(fruit, fruitBucket.get(fruit) + 1); 17 | endPoint++; 18 | currentCount++; 19 | } else if (fruitBucket.size() < 2) { 20 | fruitBucket.put(fruit, 1); 21 | endPoint++; 22 | currentCount++; 23 | } else { 24 | int fruitToBeRemoved = fruits[startPoint]; 25 | int count = fruitBucket.get(fruitToBeRemoved); 26 | 27 | if (count == 1) { 28 | fruitBucket.remove(fruitToBeRemoved); 29 | } else { 30 | fruitBucket.put(fruitToBeRemoved, count - 1); 31 | } 32 | currentCount--; 33 | startPoint++; 34 | } 35 | 36 | maxCount = Math.max(currentCount, maxCount); 37 | } 38 | 39 | return maxCount; 40 | } 41 | -------------------------------------------------------------------------------- /Sliding Window/FruitIntoBaskets.js: -------------------------------------------------------------------------------- 1 | // 904. Fruit Into Baskets 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | var totalFruit = function (fruits) { 7 | let startPoint = 0; 8 | let endPoint = 0; 9 | let fruitBucket = new Map(); 10 | let currentCount = 0; 11 | let maxCount = 0; 12 | 13 | while (startPoint < fruits.length && endPoint < fruits.length) { 14 | const fruit = fruits[endPoint]; 15 | if (fruitBucket.has(fruit)) { 16 | fruitBucket.set(fruit, fruitBucket.get(fruit) + 1); 17 | endPoint++; 18 | currentCount++; 19 | } else if (fruitBucket.size < 2) { 20 | fruitBucket.set(fruit, 1); 21 | endPoint++; 22 | currentCount++; 23 | } else { 24 | const fruitToBeRemoved = fruits[startPoint]; 25 | const count = fruitBucket.get(fruitToBeRemoved); 26 | 27 | if (count === 1) { 28 | fruitBucket.delete(fruitToBeRemoved); 29 | } else { 30 | fruitBucket.set(fruitToBeRemoved, count - 1); 31 | } 32 | currentCount--; 33 | startPoint++; 34 | } 35 | 36 | maxCount = Math.max(currentCount, maxCount); 37 | } 38 | 39 | return maxCount; 40 | }; 41 | -------------------------------------------------------------------------------- /Sliding Window/LongestSubstringWithoutRepeatingCharacters.java: -------------------------------------------------------------------------------- 1 | // 3. Longest Substring Without Repeating Characters 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | public int lengthOfLongestSubstring(String s) { 7 | if (s.length() == 0) return 0; 8 | int end = 0; 9 | int begin = 0; 10 | int maxLength = 0; 11 | HashSet map = new HashSet<>(); 12 | 13 | while (end < s.length()) { 14 | char character = s.charAt(end); 15 | if (map.contains(character)) { 16 | while (map.contains(character)) { 17 | char beginChar = s.charAt(begin); 18 | map.remove(beginChar); 19 | begin++; 20 | } 21 | } else { 22 | map.add(character); 23 | int len = end - begin + 1; 24 | if (len > maxLength) { 25 | maxLength = len; 26 | } 27 | end++; 28 | } 29 | } 30 | 31 | return maxLength; 32 | } 33 | -------------------------------------------------------------------------------- /Sliding Window/LongestSubstringWithoutRepeatingCharacters.js: -------------------------------------------------------------------------------- 1 | // 3. Longest Substring Without Repeating Characters 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | var lengthOfLongestSubstring = function (s) { 7 | if (!s.length) return 0; 8 | let end = 0; 9 | let begin = 0; 10 | let maxLength = 0; 11 | const map = new Map(); 12 | 13 | while (end < s.length) { 14 | let char = s[end]; 15 | if (map.has(char)) { 16 | while (map.has(char)) { 17 | const beginChar = s[begin]; 18 | map.delete(beginChar); 19 | begin++; 20 | } 21 | } else { 22 | map.set(char, 1); 23 | const len = end - begin + 1; 24 | if (len > maxLength) { 25 | maxLength = len; 26 | } 27 | end++; 28 | } 29 | } 30 | 31 | return maxLength; 32 | }; 33 | -------------------------------------------------------------------------------- /Sliding Window/MaxConsecutiveOnesIII.java: -------------------------------------------------------------------------------- 1 | // 1004. Max Consecutive Ones III 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: sliding window (faster because of less ops) 7 | public int longestOnes(int[] nums, int k) { 8 | int startPoint = 0; 9 | int endPoint = 0; 10 | int flipsLeft = k; 11 | int maxLength = 0; 12 | int currentLength = 0; 13 | 14 | while (endPoint < nums.length && startPoint < nums.length) { 15 | int num = nums[endPoint]; 16 | if (num == 1 || (num == 0 && flipsLeft > 0)) { 17 | endPoint++; 18 | currentLength++; 19 | if (num == 0) flipsLeft--; 20 | } else if (num == 0 && flipsLeft == 0) { 21 | if (nums[startPoint] == 0) flipsLeft++; 22 | startPoint++; 23 | currentLength--; 24 | } 25 | maxLength = Math.max(maxLength, currentLength); 26 | } 27 | 28 | return maxLength; 29 | } 30 | 31 | // Solution 2: check two pointers folder 32 | -------------------------------------------------------------------------------- /Sliding Window/MaxConsecutiveOnesIII.js: -------------------------------------------------------------------------------- 1 | // 1004. Max Consecutive Ones III 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: sliding window (faster because of less ops) 7 | var longestOnes = function (nums, k) { 8 | let startPoint = 0; 9 | let endPoint = 0; 10 | let flipsLeft = k; 11 | let maxLength = 0; 12 | let currentLength = 0; 13 | 14 | while (endPoint < nums.length && startPoint < nums.length) { 15 | const num = nums[endPoint]; 16 | if (num === 1 || (num === 0 && flipsLeft > 0)) { 17 | endPoint++; 18 | currentLength++; 19 | if (num === 0) flipsLeft--; 20 | } else if (num === 0 && flipsLeft === 0) { 21 | if (nums[startPoint] === 0) flipsLeft++; 22 | startPoint++; 23 | currentLength--; 24 | } 25 | maxLength = Math.max(maxLength, currentLength); 26 | } 27 | 28 | return maxLength; 29 | }; 30 | 31 | // Solution 2: check two pointers folder 32 | -------------------------------------------------------------------------------- /Sliding Window/MinimumWindowSubstring.java: -------------------------------------------------------------------------------- 1 | // 76. Minimum Window Substring 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | public String minWindow(String s, String t) { 7 | String result = ""; 8 | int minLen = Integer.MAX_VALUE; 9 | HashMap map = new HashMap<>(); 10 | int counter = t.length(); 11 | int begin = 0; 12 | int end = 0; 13 | 14 | for (int i = 0; i < t.length(); i++) { 15 | char character = t.charAt(i); 16 | if (map.containsKey(character)) { 17 | map.put(character, map.get(character) + 1); 18 | } else { 19 | map.put(character, 1); 20 | } 21 | } 22 | 23 | while (end <= s.length()) { 24 | if (counter == 0) { 25 | char beginChar = s.charAt(begin); 26 | if (end - begin < minLen) { 27 | minLen = end - begin; 28 | result = s.substring(begin, end); 29 | } 30 | if (map.containsKey(beginChar)) { 31 | map.put(beginChar, map.get(beginChar) + 1); 32 | if (map.get(beginChar) > 0) { 33 | counter++; 34 | } 35 | } 36 | begin++; 37 | } else { 38 | if (end < s.length()) { 39 | char endChar = s.charAt(end); 40 | if (map.containsKey(endChar)) { 41 | map.put(endChar, map.get(endChar) - 1); 42 | if (map.get(endChar) >= 0) { 43 | counter--; 44 | } 45 | } 46 | } 47 | end++; 48 | } 49 | } 50 | 51 | return result; 52 | } 53 | -------------------------------------------------------------------------------- /Sliding Window/MinimumWindowSubstring.js: -------------------------------------------------------------------------------- 1 | // 76. Minimum Window Substring 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | var minWindow = function(s, t) { 7 | let result = ""; 8 | let minLen = Number.MAX_SAFE_INTEGER; 9 | const map = new Map(); 10 | let counter = t.length; 11 | let begin = 0; 12 | let end = 0; 13 | 14 | for (const character of t) { 15 | if (map.has(character)) { 16 | map.set(character, map.get(character) + 1); 17 | } else { 18 | map.set(character, 1); 19 | } 20 | } 21 | 22 | while (end <= s.length) { 23 | if (counter === 0) { 24 | const beginChar = s[begin]; 25 | if (end - begin < minLen) { 26 | minLen = end - begin; 27 | result = s.substring(begin, end); 28 | } 29 | if (map.has(beginChar)) { 30 | map.set(beginChar, map.get(beginChar) + 1); 31 | if (map.get(beginChar) > 0) { 32 | counter++; 33 | } 34 | } 35 | begin++; 36 | } else { 37 | const endChar = s[end]; 38 | if (map.has(endChar)) { 39 | map.set(endChar, map.get(endChar) - 1); 40 | if (map.get(endChar) >= 0) { 41 | counter--; 42 | } 43 | } 44 | end++; 45 | } 46 | } 47 | 48 | return result; 49 | }; 50 | -------------------------------------------------------------------------------- /Sorting/BubbleSort.js: -------------------------------------------------------------------------------- 1 | // In each iteration we compare the current element with the next element and swap them if they are in wrong order 2 | // Optimization: If there are no swaps in the last iteration the array is sorted. (Adaptive) 3 | 4 | // Complexity Best Average Worst 5 | 6 | // Time O(n) O(n^2) O(n^2) 7 | 8 | // Space O(1) O(1) O(1) 9 | 10 | // Stable, Adaptive 11 | // Not Online 12 | 13 | function bubbleSort(arr) { 14 | for (let i = 0; i < arr.length - 1; i++) { 15 | let isSorted = true; 16 | for (let j = 0; j < arr.length - i - 1; j++) { 17 | if (arr[j + 1] < arr[j]) { 18 | [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; 19 | isSorted = false; 20 | } 21 | } 22 | if (isSorted) { 23 | return arr; 24 | } 25 | } 26 | return arr; 27 | } 28 | -------------------------------------------------------------------------------- /Sorting/InsertionSort.js: -------------------------------------------------------------------------------- 1 | // We take an element from the unsorted part and insert it in the right place in the sorted part 2 | // Initially one element would be sorted because a single elment is always sorted in itself 3 | 4 | // Complexity Best Average Worst 5 | 6 | // Time O(n) O(n^2) O(n^2) 7 | 8 | // Space O(1) O(1) O(1) 9 | 10 | // Stable, Adaptive, Online 11 | 12 | function insertionSort(arr) { 13 | for (let i = 1; i < arr.length; i++) { 14 | let j = i; 15 | while (arr[j - 1] > arr[j] && j >= 0) { 16 | [arr[j - 1], arr[j]] = [arr[j], arr[j - 1]]; 17 | j--; 18 | } 19 | } 20 | return arr; 21 | } 22 | -------------------------------------------------------------------------------- /Sorting/MergeSort.js: -------------------------------------------------------------------------------- 1 | // Implementation 1 2 | 3 | // We split the array in half and then recursively splits the halves untill we have an array of one element. 4 | // A single element is always sorted in itself so we can recursively merge the parts to get a sorted array. 5 | 6 | // Time Complexity O(nlogn) 7 | // Space Complexity O(nlogn) 8 | 9 | function mergeSort(arr) { 10 | if (arr.length === 1) { 11 | return arr; 12 | } 13 | const middleIdx = Math.trunc(arr.length / 2); 14 | const leftHalf = mergeSort(arr.slice(0, middleIdx)); 15 | const rightHalf = mergeSort(arr.slice(middleIdx)); 16 | return merge(leftHalf, rightHalf); 17 | } 18 | 19 | function merge(arr1, arr2) { 20 | const mergedArray = []; 21 | let i = 0; 22 | let j = 0; 23 | while (i < arr1.length && j < arr2.length) { 24 | if (arr1[i] < arr2[j]) { 25 | mergedArray.push(arr1[i++]); 26 | } else { 27 | mergedArray.push(arr2[j++]); 28 | } 29 | } 30 | while (i < arr1.length) { 31 | mergedArray.push(arr1[i++]); 32 | } 33 | while (j < arr2.length) { 34 | mergedArray.push(arr2[j++]); 35 | } 36 | return mergedArray; 37 | } 38 | 39 | 40 | // Implementation 2 41 | 42 | // Time Complexity O(nlogn) 43 | // Space Complexity O(n) 44 | -------------------------------------------------------------------------------- /Sorting/QuickSort.js: -------------------------------------------------------------------------------- 1 | function pivotHelper(arr, startIdx = 0, endIdx = arr.length) { 2 | function swap(elem1, elem2) { 3 | [arr[elem1], arr[elem2]] = [arr[elem2], arr[elem1]]; 4 | } 5 | const pivot = arr[startIdx]; 6 | let pivotIndx = startIdx; 7 | for (let i = startIdx + 1; i < endIdx; i++) { 8 | if (pivot > arr[i]) { 9 | pivotIndx++; 10 | swap(i, pivotIndx); 11 | } 12 | } 13 | swap(startIdx, pivotIndx); 14 | return pivotIndx; 15 | } 16 | 17 | function quickSort(arr, startIdx = 0, endIdx = arr.length) { 18 | if (startIdx < endIdx) { 19 | const pivotIdx = pivotHelper(arr, startIdx, endIdx); 20 | if (endIdx - pivotIdx < pivotIdx - startIdx) { 21 | quickSort(arr, pivotIdx + 1, endIdx); 22 | quickSort(arr, startIdx, pivotIdx); 23 | } else { 24 | quickSort(arr, startIdx, pivotIdx); 25 | quickSort(arr, pivotIdx + 1, endIdx); 26 | } 27 | } 28 | return arr; 29 | } 30 | -------------------------------------------------------------------------------- /Sorting/README.md: -------------------------------------------------------------------------------- 1 | # Other Parameters to consider apart from time and space complexity while selecting a sorting algorithm 2 | 3 | 1. Stable - Does not change the relative order of the equal elements in the initial array 4 | 2. Adaptive - Efficient for data that is substantially sorted 5 | 3. Online - Can sort a list as it receives it 6 | 7 | [Video Explanation](https://youtu.be/4gW6P5A1gxs) 8 | -------------------------------------------------------------------------------- /Sorting/RadixSort.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function getDigit(num, pos) { 4 | return Math.floor(Math.abs(num) / Math.pow(10, pos)) % 10; 5 | } 6 | 7 | function getNumberOfDigits(num) { 8 | if (num === 0) return 1; 9 | return Math.floor(Math.log10(Math.abs(num))) + 1; 10 | } 11 | 12 | function getMaxNumberOfDigits(nums) { 13 | let maxDigits = 0; 14 | for (const num of nums) { 15 | maxDigits = Math.max(maxDigits, getNumberOfDigits(num)); 16 | } 17 | return maxDigits; 18 | } 19 | 20 | function radixSort(nums) { 21 | const maxDigits = getMaxNumberOfDigits(nums); 22 | console.log(maxDigits); 23 | for (let i = 0; i < maxDigits; i++) { 24 | const buckets = []; 25 | for (const num of nums) { 26 | const digit = getDigit(num, i); 27 | if (buckets[digit]) { 28 | buckets[digit].push(num); 29 | } else { 30 | buckets[digit] = [num]; 31 | } 32 | } 33 | nums = buckets.flat(); 34 | } 35 | return nums; 36 | } 37 | -------------------------------------------------------------------------------- /Sorting/SelectionSort.js: -------------------------------------------------------------------------------- 1 | // In each iteration we select the minimum element from the unsorted part of the array and replace it with the first unsorted element 2 | 3 | // Same for best, avg and worst case 4 | // Time Complexity O(n^2) 5 | // Space Complexity O(1) 6 | 7 | // Not Stable, Not Adaptive, Not Online 8 | // We can make this algorithm stable by rotating all elements to the right and putting the min element in the empty slot. 9 | 10 | function selectionSort(arr) { 11 | for (let i = 0; i < arr.length - 1; i++) { 12 | let minPos = i; 13 | for (let j = i + 1; j < arr.length; j++) { 14 | if (arr[j] < arr[minPos]) { 15 | minPos = j; 16 | } 17 | } 18 | if (minPos !== i) { 19 | [arr[i], arr[minPos]] = [arr[minPos], arr[i]]; 20 | } 21 | } 22 | return arr; 23 | } 24 | -------------------------------------------------------------------------------- /StacksNQueues/BackspaceStringCompare.java: -------------------------------------------------------------------------------- 1 | // 844. Backspace String Compare 2 | 3 | // Solution 1: Using Stack 4 | // Time Complexity O(n+m) 5 | // Space Complexity O(n+m) 6 | 7 | public static boolean backspaceCompare(String s, String t) { 8 | Stack string1 = new Stack<>(); 9 | Stack string2 = new Stack<>(); 10 | 11 | createArrayOfString(s, string1); 12 | createArrayOfString(t, string2); 13 | 14 | if (string1.size() != string2.size())return false; 15 | if(string1.isEmpty() && string2.isEmpty())return true; 16 | for (int i = 0; i < string1.size(); i++) { 17 | if (string1.elementAt(i) != string2.elementAt(i)) return false; 18 | } 19 | return true; 20 | }; 21 | 22 | public static void createArrayOfString(String string, Stack stack) { 23 | for (int i = 0; i < string.length(); i++) { 24 | if (string.charAt(i) == '#') { 25 | if(!stack.isEmpty()) 26 | stack.pop(); 27 | } else{ 28 | stack.push(string.charAt(i)); 29 | } 30 | } 31 | } 32 | 33 | // Solution 2: in 2 pointer folder 34 | -------------------------------------------------------------------------------- /StacksNQueues/BackspaceStringCompare.js: -------------------------------------------------------------------------------- 1 | // 844. Backspace String Compare 2 | 3 | // Solution 1: Using Stack 4 | // Time Complexity O(n+m) 5 | // Space Complexity O(n+m) 6 | 7 | var backspaceCompare = function(s, t) { 8 | const string1 = []; 9 | const string2 = []; 10 | 11 | function createArrayOfString(string, array) { 12 | for (const char of string) { 13 | if (char === "#") { 14 | array.pop(); 15 | } else { 16 | array.push(char); 17 | } 18 | } 19 | } 20 | 21 | createArrayOfString(s, string1); 22 | createArrayOfString(t, string2); 23 | 24 | if (string1.length !== string2.length) return false; 25 | for (let i = 0; i < string1.length; i++) { 26 | if (string1[i] !== string2[i]) return false; 27 | } 28 | return true; 29 | }; 30 | 31 | // Solution 2: in 2 pointer folder 32 | -------------------------------------------------------------------------------- /StacksNQueues/ValidParentheses.java: -------------------------------------------------------------------------------- 1 | // 20. Valid Parentheses 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | class Solution { 7 | public boolean isValid(String s) { 8 | if (s.length() % 2 != 0) { 9 | return false; 10 | } 11 | 12 | HashMap map = new HashMap<>(); 13 | Stack stack = new Stack<>(); 14 | map.put("{", "}"); 15 | map.put("(", ")"); 16 | map.put("[", "]"); 17 | 18 | for (int i = 0; i < s.length(); i++) { 19 | String currentParentheses = String.valueOf(s.charAt(i)); 20 | if (map.get(currentParentheses) != null) { 21 | stack.push(currentParentheses); 22 | } else { 23 | if (stack.empty()) { 24 | return false; 25 | } 26 | String lastElement = stack.peek(); 27 | if (currentParentheses.equals(map.get(lastElement))) { 28 | stack.pop(); 29 | } else { 30 | return false; 31 | } 32 | } 33 | } 34 | 35 | return stack.empty(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /StacksNQueues/ValidParentheses.js: -------------------------------------------------------------------------------- 1 | // 20. Valid Parentheses 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(n) 5 | 6 | var isValid = function (s) { 7 | if (s.length % 2 !== 0) { 8 | return false; 9 | } 10 | 11 | const map = { 12 | "{": "}", 13 | "[": "]", 14 | "(": ")", 15 | }; 16 | const stack = []; 17 | 18 | for (let i = 0; i < s.length; i++) { 19 | if (map[s[i]]) { 20 | stack.push(s[i]); 21 | } else { 22 | const lastElement = stack[stack.length - 1]; 23 | if (s[i] === map[lastElement]) { 24 | stack.pop(); 25 | } else { 26 | return false; 27 | } 28 | } 29 | } 30 | 31 | return stack.length === 0; 32 | }; 33 | -------------------------------------------------------------------------------- /Strings/LowerUpper.js: -------------------------------------------------------------------------------- 1 | // convert a string to upper or lower case 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | function toLower(str) { 7 | let result = ""; 8 | for (let i = 0; i < str.length; i++) { 9 | if (str.charAt(i) >= "A" && str.charAt(i) <= "Z") 10 | result += String.fromCharCode(str.charCodeAt(i) + 32); 11 | else result += str.charAt(i); 12 | } 13 | return result; 14 | } 15 | 16 | function toUpper(str) { 17 | let result = ""; 18 | for (let i = 0; i < str.length; i++) { 19 | if (str.charAt(i) >= "a" && str.charAt(i) <= "z") 20 | result += String.fromCharCode(str.charCodeAt(i) - 32); 21 | else result += str.charAt(i); 22 | } 23 | return result; 24 | } 25 | -------------------------------------------------------------------------------- /Strings/MaxFreq.js: -------------------------------------------------------------------------------- 1 | // find the character occuring max times in the string 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // supporting function 7 | 8 | function toLower(str) { 9 | let result = ""; 10 | for (let i = 0; i < str.length; i++) { 11 | if (str.charAt(i) >= "A" && str.charAt(i) <= "Z") 12 | result += String.fromCharCode(str.charCodeAt(i) + 32); 13 | else result += str.charAt(i); 14 | } 15 | return result; 16 | } 17 | 18 | function maxFreq(str) { 19 | let count = []; 20 | for (let i = 0; i < 26; i++) count[i] = 0; 21 | for (let i = 0; i < str.length; i++) { 22 | if (str.charAt(i) >= "a") count[str.charCodeAt(i) - 97]++; 23 | if (str.charAt(i) < "a") count[str.charCodeAt(i) - 65]++; 24 | } 25 | let max = 0; 26 | let ans = ""; 27 | for (let i = 0; i < count.length; i++) { 28 | if (count[i] > max) { 29 | max = count[i]; 30 | ans = String.fromCharCode(i + 97); 31 | } 32 | } 33 | return ans; 34 | } 35 | -------------------------------------------------------------------------------- /TwoPointers/BackspaceStringCompare.java: -------------------------------------------------------------------------------- 1 | // 844. Backspace String Compare 2 | 3 | // Solution 1: using 2 pointer 4 | // Time Complexity O(n+m) 5 | // Space Complexity O(1) 6 | 7 | public static boolean backspaceCompare(String s, String t) { 8 | int ptr1 = s.length() - 1; 9 | int ptr2 = t.length() - 1; 10 | int sBackSpaceCount = 0; 11 | int tBackSpaceCount = 0; 12 | 13 | while (ptr1 >= 0 || ptr2 >= 0) { 14 | if (sBackSpaceCount == 0 && tBackSpaceCount == 0) { 15 | if (ptr1 >= 0 && ptr2 >= 0 && s.charAt(ptr1) != '#' && t.charAt(ptr2) != '#') { 16 | if (s.charAt(ptr1) != t.charAt(ptr2)) { 17 | return false; 18 | } else { 19 | ptr1--; 20 | ptr2--; 21 | } 22 | } else { 23 | boolean flag = false; 24 | if (ptr1 >= 0 && s.charAt(ptr1) == '#') { 25 | sBackSpaceCount++; 26 | ptr1--; 27 | flag = true; 28 | } 29 | if (ptr2 >= 0 && t.charAt(ptr2) == '#') { 30 | tBackSpaceCount++; 31 | ptr2--; 32 | flag = true; 33 | } 34 | if (!flag) { 35 | return false; 36 | } 37 | } 38 | } else { 39 | while (sBackSpaceCount != 0) { 40 | if (ptr1 >= 0) { 41 | if (s.charAt(ptr1) == '#') { 42 | sBackSpaceCount++; 43 | ptr1--; 44 | } else { 45 | sBackSpaceCount--; 46 | ptr1--; 47 | } 48 | } else { 49 | sBackSpaceCount = 0; 50 | } 51 | } 52 | while (tBackSpaceCount != 0) { 53 | if (ptr2 >= 0) { 54 | if (t.charAt(ptr2) == '#') { 55 | tBackSpaceCount++; 56 | ptr2--; 57 | } else { 58 | tBackSpaceCount--; 59 | ptr2--; 60 | } 61 | } else { 62 | tBackSpaceCount = 0; 63 | } 64 | } 65 | } 66 | } 67 | return true; 68 | } 69 | 70 | // Solution 2: in stack and queue folder 71 | -------------------------------------------------------------------------------- /TwoPointers/BackspaceStringCompare.js: -------------------------------------------------------------------------------- 1 | // 844. Backspace String Compare 2 | 3 | // Solution 1: using 2 pointer 4 | // Time Complexity O(n+m) 5 | // Space Complexity O(1) 6 | 7 | var backspaceCompare = function (s, t) { 8 | let ptr1 = s.length - 1; 9 | let ptr2 = t.length - 1; 10 | let sBackSpaceCount = 0; 11 | let tBackSpaceCount = 0; 12 | 13 | while (ptr1 >= 0 || ptr2 >= 0) { 14 | if (sBackSpaceCount === 0 && tBackSpaceCount === 0) { 15 | if (s[ptr1] !== "#" && t[ptr2] !== "#") { 16 | if (s[ptr1] !== t[ptr2]) { 17 | return false; 18 | } else { 19 | ptr1--; 20 | ptr2--; 21 | } 22 | } else { 23 | if (s[ptr1] === "#") { 24 | sBackSpaceCount++; 25 | ptr1--; 26 | } 27 | if (t[ptr2] === "#") { 28 | tBackSpaceCount++; 29 | ptr2--; 30 | } 31 | } 32 | } else { 33 | while (sBackSpaceCount !== 0) { 34 | if (s[ptr1] === "#") { 35 | sBackSpaceCount++; 36 | ptr1--; 37 | } else { 38 | sBackSpaceCount--; 39 | ptr1--; 40 | } 41 | } 42 | while (tBackSpaceCount !== 0) { 43 | if (t[ptr2] === "#") { 44 | tBackSpaceCount++; 45 | ptr2--; 46 | } else { 47 | tBackSpaceCount--; 48 | ptr2--; 49 | } 50 | } 51 | } 52 | } 53 | return true; 54 | }; 55 | 56 | // Solution 2: in stack and queue folder 57 | -------------------------------------------------------------------------------- /TwoPointers/FruitIntoBaskets.java: -------------------------------------------------------------------------------- 1 | // 904. Fruit Into Baskets 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: two pointer approach 7 | public int totalFruit(int[] fruits) { 8 | int maxFruits = 0; 9 | int lastFruit = 0; 10 | int startPoint = 0; 11 | int count = 0; 12 | int[] types = {fruits[0], fruits[0]}; 13 | 14 | while (startPoint < fruits.length) { 15 | int currentFruit = fruits[startPoint]; 16 | if (currentFruit == types[0] || currentFruit == types[1]) { 17 | count++; 18 | startPoint++; 19 | } else if (types[0] == types[1]) { 20 | types[1] = currentFruit; 21 | lastFruit = startPoint; 22 | count++; 23 | startPoint++; 24 | } else { 25 | startPoint = lastFruit; 26 | types[0] = types[1]; 27 | count = 0; 28 | } 29 | maxFruits = Math.max(maxFruits, count); 30 | } 31 | 32 | return maxFruits; 33 | } 34 | 35 | // Solution 2: check sliding window folder 36 | -------------------------------------------------------------------------------- /TwoPointers/FruitIntoBaskets.js: -------------------------------------------------------------------------------- 1 | // 904. Fruit Into Baskets 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: two pointer approach 7 | var totalFruit = function (fruits) { 8 | let maxFruits = 0; 9 | let lastFruit = 0; 10 | let startPoint = 0; 11 | let count = 0; 12 | let types = [fruits[0], fruits[0]]; 13 | 14 | while (startPoint < fruits.length) { 15 | let currentFruit = fruits[startPoint]; 16 | if (currentFruit === types[0] || currentFruit === types[1]) { 17 | count++; 18 | startPoint++; 19 | } else if (types[0] === types[1]) { 20 | types[1] = currentFruit; 21 | lastFruit = startPoint; 22 | count++; 23 | startPoint++; 24 | } else { 25 | startPoint = lastFruit; 26 | types[0] = types[1]; 27 | count = 0; 28 | } 29 | maxFruits = Math.max(maxFruits, count); 30 | } 31 | 32 | return maxFruits; 33 | }; 34 | 35 | // Solution 2: check sliding window folder 36 | -------------------------------------------------------------------------------- /TwoPointers/IntersectionOfTwoArrays.java: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // assuming arrays are sorted 4 | // Solution 1: Using 2 pointers 5 | // Time Complexity: O(n) 6 | // Space Complexity: O(1) 7 | 8 | public int[] intersection(int[] nums1, int[] nums2) { 9 | Arrays.sort(nums1); 10 | Arrays.sort(nums2); 11 | ArrayList list = new ArrayList(); 12 | int ptr1 = 0; 13 | int ptr2 = 0; 14 | 15 | while (ptr1 < nums1.length && ptr2 < nums2.length) { 16 | if (nums1[ptr1] < nums2[ptr2]) { 17 | ptr1 = goToNextValue(ptr1, nums1); 18 | } else if (nums1[ptr1] > nums2[ptr2]) { 19 | ptr2 = goToNextValue(ptr2, nums2); 20 | } else { 21 | list.add(nums1[ptr1]); 22 | ptr1 = goToNextValue(ptr1, nums1); 23 | ptr2 = goToNextValue(ptr2, nums2); 24 | } 25 | } 26 | 27 | int[] output = new int[list.size()]; 28 | for (int i = 0; i < list.size(); i++) { 29 | output[i] = list.get(i); 30 | } 31 | return output; 32 | } 33 | 34 | public int goToNextValue(int pointer, int[] array) { 35 | int prevValue = array[pointer]; 36 | while (pointer < array.length && array[pointer] == prevValue) { 37 | pointer++; 38 | } 39 | return pointer; 40 | } 41 | 42 | // Solution 2: in arrays folder 43 | // Solution 3: in search folder 44 | -------------------------------------------------------------------------------- /TwoPointers/IntersectionOfTwoArrays.js: -------------------------------------------------------------------------------- 1 | // 349. Intersection of Two Arrays 2 | 3 | // assuming arrays are sorted 4 | // Solution 1: Using 2 pointers 5 | // Time Complexity: O(n) 6 | // Space Complexity: O(1) 7 | 8 | var intersection = function(nums1, nums2) { 9 | nums1.sort((a, b) => a - b); 10 | nums2.sort((a, b) => a - b); 11 | let ptr1 = 0; 12 | let ptr2 = 0; 13 | const output = []; 14 | 15 | while (ptr1 < nums1.length && ptr2 < nums2.length) { 16 | if (nums1[ptr1] < nums2[ptr2]) { 17 | ptr1 = goToNextValue(ptr1, nums1); 18 | } else if (nums1[ptr1] > nums2[ptr2]) { 19 | ptr2 = goToNextValue(ptr2, nums2); 20 | } else { 21 | output.push(nums1[ptr1]); 22 | ptr1 = goToNextValue(ptr1, nums1); 23 | ptr2 = goToNextValue(ptr2, nums2); 24 | } 25 | } 26 | return output; 27 | }; 28 | 29 | function goToNextValue(pointer, array) { 30 | const prevValue = array[pointer]; 31 | while (array[pointer] === prevValue) { 32 | pointer++; 33 | } 34 | return pointer; 35 | } 36 | 37 | // Solution 2: in arrays folder 38 | // Solution 3: in search folder 39 | -------------------------------------------------------------------------------- /TwoPointers/LongPressedName.java: -------------------------------------------------------------------------------- 1 | // 925. Long Pressed Name 2 | 3 | // Time Complexity O(n+m) 4 | // Space Complexity O(1) 5 | 6 | public boolean isLongPressedName(String name, String typed) { 7 | if (typed.length() < name.length()) return false; 8 | int namePtr = 0; 9 | int typedPtr = 0; 10 | 11 | while (typedPtr < typed.length() || namePtr < name.length()) { 12 | if(typedPtr >= typed.length()) return false; 13 | if (namePtr < name.length() && name.charAt(namePtr) == typed.charAt(typedPtr)) { 14 | namePtr++; 15 | typedPtr++; 16 | } else if (namePtr != 0 && name.charAt(namePtr - 1) == typed.charAt(typedPtr)) { 17 | typedPtr++; 18 | } else { 19 | return false; 20 | } 21 | } 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /TwoPointers/LongPressedName.js: -------------------------------------------------------------------------------- 1 | // 925. Long Pressed Name 2 | 3 | // Time Complexity O(n+m) 4 | // Space Complexity O(1) 5 | 6 | var isLongPressedName = function (name, typed) { 7 | if (typed.length < name.length) return false; 8 | let namePtr = 0; 9 | let typedPtr = 0; 10 | 11 | while (typedPtr < typed.length || namePtr < name.length) { 12 | if (name[namePtr] === typed[typedPtr]) { 13 | namePtr++; 14 | typedPtr++; 15 | } else if (name[namePtr - 1] === typed[typedPtr]) { 16 | typedPtr++; 17 | } else { 18 | return false; 19 | } 20 | } 21 | return true; 22 | }; 23 | -------------------------------------------------------------------------------- /TwoPointers/MaxConsecutiveOnesIII.java: -------------------------------------------------------------------------------- 1 | // 1004. Max Consecutive Ones III 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: two pointer approach (slower because of more ops) 7 | public int longestOnes(int[] nums, int k) { 8 | int flipsLeft = k; 9 | int maxCount = 0; 10 | int count = 0; 11 | int flipPoint = 0; 12 | int startPoint = 0; 13 | 14 | while (startPoint < nums.length) { 15 | int num = nums[startPoint]; 16 | if (num == 1) { 17 | count++; 18 | startPoint++; 19 | } else if (flipsLeft > 0) { 20 | if (flipsLeft == k) flipPoint = startPoint; 21 | count++; 22 | startPoint++; 23 | flipsLeft--; 24 | } else { 25 | count = 0; 26 | flipsLeft = k; 27 | startPoint = flipPoint + 1; 28 | if (k == 0) flipPoint = startPoint; 29 | } 30 | maxCount = Math.max(maxCount, count); 31 | } 32 | 33 | return maxCount; 34 | } 35 | 36 | // Solution 2: check sliding window folder 37 | -------------------------------------------------------------------------------- /TwoPointers/MaxConsecutiveOnesIII.js: -------------------------------------------------------------------------------- 1 | // 1004. Max Consecutive Ones III 2 | 3 | // Time Complexity O(n) 4 | // Space Complexity O(1) 5 | 6 | // Solution 1: two pointer approach (slower because of more ops) 7 | var longestOnes = function(nums, k) { 8 | let flipsLeft = k; 9 | let maxCount = 0; 10 | let count = 0; 11 | let flipPoint = 0; 12 | let startPoint = 0; 13 | 14 | while (startPoint < nums.length) { 15 | const num = nums[startPoint]; 16 | if (num === 1) { 17 | count++; 18 | startPoint++; 19 | } else if (flipsLeft > 0) { 20 | if (flipsLeft === k) flipPoint = startPoint; 21 | count++; 22 | startPoint++; 23 | flipsLeft--; 24 | } else { 25 | count = 0; 26 | flipsLeft = k; 27 | startPoint = flipPoint + 1; 28 | if (k === 0) flipPoint = startPoint; 29 | } 30 | maxCount = Math.max(maxCount, count); 31 | } 32 | 33 | return maxCount; 34 | }; 35 | 36 | // Solution 2: check sliding window folder 37 | -------------------------------------------------------------------------------- /TwoPointers/TwoSumSorted.js: -------------------------------------------------------------------------------- 1 | // Time Complexity O(n) 2 | // Space Complexity O(1) 3 | 4 | var twoSum = function(numbers, target) { 5 | let leftPtr = 0; 6 | let rightPtr = numbers.length - 1; 7 | 8 | while(leftPtr < rightPtr){ 9 | const sum = numbers[leftPtr] + numbers[rightPtr]; 10 | if (sum === target) 11 | return [++leftPtr, ++rightPtr]; 12 | else if (sum > target) 13 | rightPtr--; 14 | else 15 | leftPtr++; 16 | } 17 | }; 18 | --------------------------------------------------------------------------------