DEV Community

Mahendranath Reddy
Mahendranath Reddy

Posted on

JavaScript Practice Coding Examples - Interview Guidance for Problems

JavaScript Practice Coding Examples

Table of Contents

  1. Easy Level
  2. Medium Level
  3. Hard Level
  4. Array Manipulation
  5. String Manipulation
  6. Object & Data Structures
  7. Recursion & Algorithms
  8. Functional Programming
  9. Async & Promises
  10. DOM & Browser APIs

Easy Level

1. Two Sum

Problem: Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
function twoSum(nums, target) {
  const map = new Map();

  for (let i = 0; i < nums.length; i++) {
    const complement = target - nums[i];

    if (map.has(complement)) {
      return [map.get(complement), i];
    }

    map.set(nums[i], i);
  }

  return [];
}

// Test cases
console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]
console.log(twoSum([3, 2, 4], 6)); // [1, 2]
console.log(twoSum([3, 3], 6)); // [0, 1]

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

2. Reverse String

Problem: Write a function that reverses a string.

/**
 * @param {string} s
 * @return {string}
 */
function reverseString(s) {
  return s.split('').reverse().join('');
}

// Alternative: Using two pointers
function reverseStringTwoPointers(s) {
  const arr = s.split('');
  let left = 0;
  let right = arr.length - 1;

  while (left < right) {
    [arr[left], arr[right]] = [arr[right], arr[left]];
    left++;
    right--;
  }

  return arr.join('');
}

// Test cases
console.log(reverseString("hello")); // "olleh"
console.log(reverseStringTwoPointers("world")); // "dlrow"

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

3. Palindrome Check

Problem: Determine if a string is a palindrome.

/**
 * @param {string} s
 * @return {boolean}
 */
function isPalindrome(s) {
  const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, '');
  return cleaned === cleaned.split('').reverse().join('');
}

// Alternative: Two pointers
function isPalindromeTwoPointers(s) {
  const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, '');
  let left = 0;
  let right = cleaned.length - 1;

  while (left < right) {
    if (cleaned[left] !== cleaned[right]) {
      return false;
    }
    left++;
    right--;
  }

  return true;
}

// Test cases
console.log(isPalindrome("A man, a plan, a canal: Panama")); // true
console.log(isPalindrome("race a car")); // false
console.log(isPalindromeTwoPointers("Was it a car or a cat I saw?")); // true

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

4. FizzBuzz

Problem: Write a program that prints numbers from 1 to n. For multiples of 3 print "Fizz", for multiples of 5 print "Buzz", and for multiples of both print "FizzBuzz".

/**
 * @param {number} n
 * @return {string[]}
 */
function fizzBuzz(n) {
  const result = [];

  for (let i = 1; i <= n; i++) {
    if (i % 15 === 0) {
      result.push("FizzBuzz");
    } else if (i % 3 === 0) {
      result.push("Fizz");
    } else if (i % 5 === 0) {
      result.push("Buzz");
    } else {
      result.push(i.toString());
    }
  }

  return result;
}

// Test cases
console.log(fizzBuzz(15)); 
// ["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"]

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

5. Maximum Subarray

Problem: Find the contiguous subarray with the largest sum.

/**
 * @param {number[]} nums
 * @return {number}
 */
function maxSubArray(nums) {
  let maxSum = nums[0];
  let currentSum = nums[0];

  for (let i = 1; i < nums.length; i++) {
    currentSum = Math.max(nums[i], currentSum + nums[i]);
    maxSum = Math.max(maxSum, currentSum);
  }

  return maxSum;
}

// Test cases
console.log(maxSubArray([-2,1,-3,4,-1,2,1,-5,4])); // 6
console.log(maxSubArray([1])); // 1
console.log(maxSubArray([5,4,-1,7,8])); // 23

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

Medium Level

6. Longest Substring Without Repeating Characters

Problem: Find the length of the longest substring without repeating characters.

/**
 * @param {string} s
 * @return {number}
 */
function lengthOfLongestSubstring(s) {
  let maxLength = 0;
  let left = 0;
  const charSet = new Set();

  for (let right = 0; right < s.length; right++) {
    while (charSet.has(s[right])) {
      charSet.delete(s[left]);
      left++;
    }
    charSet.add(s[right]);
    maxLength = Math.max(maxLength, right - left + 1);
  }

  return maxLength;
}

// Test cases
console.log(lengthOfLongestSubstring("abcabcbb")); // 3
console.log(lengthOfLongestSubstring("bbbbb")); // 1
console.log(lengthOfLongestSubstring("pwwkew")); // 3

// Time Complexity: O(n)
// Space Complexity: O(min(m,n)) where m is charset size
Enter fullscreen mode Exit fullscreen mode

7. Valid Parentheses

Problem: Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

/**
 * @param {string} s
 * @return {boolean}
 */
function isValid(s) {
  const stack = [];
  const pairs = {
    ')': '(',
    '}': '{',
    ']': '['
  };

  for (const char of s) {
    if (char in pairs) {
      if (stack.length === 0 || stack.pop() !== pairs[char]) {
        return false;
      }
    } else {
      stack.push(char);
    }
  }

  return stack.length === 0;
}

// Test cases
console.log(isValid("()")); // true
console.log(isValid("()[]{}")); // true
console.log(isValid("(]")); // false
console.log(isValid("([)]")); // false
console.log(isValid("{[]}")); // true

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

8. Merge Two Sorted Arrays

Problem: Merge two sorted arrays into one sorted array.

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
function mergeSortedArrays(nums1, nums2) {
  const result = [];
  let i = 0;
  let j = 0;

  while (i < nums1.length && j < nums2.length) {
    if (nums1[i] <= nums2[j]) {
      result.push(nums1[i]);
      i++;
    } else {
      result.push(nums2[j]);
      j++;
    }
  }

  // Add remaining elements
  while (i < nums1.length) {
    result.push(nums1[i]);
    i++;
  }

  while (j < nums2.length) {
    result.push(nums2[j]);
    j++;
  }

  return result;
}

// Test cases
console.log(mergeSortedArrays([1,3,5], [2,4,6])); // [1,2,3,4,5,6]
console.log(mergeSortedArrays([1,2,3], [])); // [1,2,3]
console.log(mergeSortedArrays([], [4,5,6])); // [4,5,6]

// Time Complexity: O(n + m)
// Space Complexity: O(n + m)
Enter fullscreen mode Exit fullscreen mode

9. Binary Search

Problem: Implement binary search on a sorted array.

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
function binarySearch(nums, target) {
  let left = 0;
  let right = nums.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (nums[mid] === target) {
      return mid;
    } else if (nums[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }

  return -1;
}

// Test cases
console.log(binarySearch([-1,0,3,5,9,12], 9)); // 4
console.log(binarySearch([-1,0,3,5,9,12], 2)); // -1

// Time Complexity: O(log n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

10. Group Anagrams

Problem: Group anagrams together from an array of strings.

/**
 * @param {string[]} strs
 * @return {string[][]}
 */
function groupAnagrams(strs) {
  const map = new Map();

  for (const str of strs) {
    const sorted = str.split('').sort().join('');

    if (!map.has(sorted)) {
      map.set(sorted, []);
    }

    map.get(sorted).push(str);
  }

  return Array.from(map.values());
}

// Test cases
console.log(groupAnagrams(["eat","tea","tan","ate","nat","bat"]));
// [["eat","tea","ate"],["tan","nat"],["bat"]]

// Time Complexity: O(n * k log k) where k is max string length
// Space Complexity: O(n * k)
Enter fullscreen mode Exit fullscreen mode

Hard Level

11. Median of Two Sorted Arrays

Problem: Find the median of two sorted arrays.

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
function findMedianSortedArrays(nums1, nums2) {
  // Ensure nums1 is the smaller array
  if (nums1.length > nums2.length) {
    [nums1, nums2] = [nums2, nums1];
  }

  const m = nums1.length;
  const n = nums2.length;
  let left = 0;
  let right = m;

  while (left <= right) {
    const partition1 = Math.floor((left + right) / 2);
    const partition2 = Math.floor((m + n + 1) / 2) - partition1;

    const maxLeft1 = partition1 === 0 ? -Infinity : nums1[partition1 - 1];
    const minRight1 = partition1 === m ? Infinity : nums1[partition1];
    const maxLeft2 = partition2 === 0 ? -Infinity : nums2[partition2 - 1];
    const minRight2 = partition2 === n ? Infinity : nums2[partition2];

    if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {
      if ((m + n) % 2 === 0) {
        return (Math.max(maxLeft1, maxLeft2) + Math.min(minRight1, minRight2)) / 2;
      } else {
        return Math.max(maxLeft1, maxLeft2);
      }
    } else if (maxLeft1 > minRight2) {
      right = partition1 - 1;
    } else {
      left = partition1 + 1;
    }
  }

  throw new Error("Input arrays are not sorted");
}

// Test cases
console.log(findMedianSortedArrays([1,3], [2])); // 2
console.log(findMedianSortedArrays([1,2], [3,4])); // 2.5

// Time Complexity: O(log(min(m,n)))
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

12. Longest Palindromic Substring

Problem: Find the longest palindromic substring.

/**
 * @param {string} s
 * @return {string}
 */
function longestPalindrome(s) {
  if (s.length < 2) return s;

  let start = 0;
  let maxLength = 1;

  function expandAroundCenter(left, right) {
    while (left >= 0 && right < s.length && s[left] === s[right]) {
      const currentLength = right - left + 1;
      if (currentLength > maxLength) {
        start = left;
        maxLength = currentLength;
      }
      left--;
      right++;
    }
  }

  for (let i = 0; i < s.length; i++) {
    expandAroundCenter(i, i);     // Odd length
    expandAroundCenter(i, i + 1); // Even length
  }

  return s.substring(start, start + maxLength);
}

// Test cases
console.log(longestPalindrome("babad")); // "bab" or "aba"
console.log(longestPalindrome("cbbd")); // "bb"

// Time Complexity: O(n^2)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

13. Regular Expression Matching

Problem: Implement regular expression matching with support for '.' and '*'.

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
function isMatch(s, p) {
  const dp = Array(s.length + 1).fill(null).map(() => Array(p.length + 1).fill(false));

  dp[0][0] = true;

  // Handle patterns like a*, a*b*, a*b*c*
  for (let j = 1; j <= p.length; j++) {
    if (p[j - 1] === '*') {
      dp[0][j] = dp[0][j - 2];
    }
  }

  for (let i = 1; i <= s.length; i++) {
    for (let j = 1; j <= p.length; j++) {
      if (p[j - 1] === '*') {
        // Two cases: 
        // 1. Zero occurrences of the character before *
        // 2. One or more occurrences
        dp[i][j] = dp[i][j - 2] || 
                  (dp[i - 1][j] && (s[i - 1] === p[j - 2] || p[j - 2] === '.'));
      } else {
        dp[i][j] = dp[i - 1][j - 1] && 
                  (s[i - 1] === p[j - 1] || p[j - 1] === '.');
      }
    }
  }

  return dp[s.length][p.length];
}

// Test cases
console.log(isMatch("aa", "a")); // false
console.log(isMatch("aa", "a*")); // true
console.log(isMatch("ab", ".*")); // true

// Time Complexity: O(m * n)
// Space Complexity: O(m * n)
Enter fullscreen mode Exit fullscreen mode

14. Trapping Rain Water

Problem: Calculate how much water can be trapped after raining.

/**
 * @param {number[]} height
 * @return {number}
 */
function trap(height) {
  if (height.length === 0) return 0;

  let left = 0;
  let right = height.length - 1;
  let leftMax = 0;
  let rightMax = 0;
  let water = 0;

  while (left < right) {
    if (height[left] < height[right]) {
      if (height[left] >= leftMax) {
        leftMax = height[left];
      } else {
        water += leftMax - height[left];
      }
      left++;
    } else {
      if (height[right] >= rightMax) {
        rightMax = height[right];
      } else {
        water += rightMax - height[right];
      }
      right--;
    }
  }

  return water;
}

// Test cases
console.log(trap([0,1,0,2,1,0,1,3,2,1,2,1])); // 6
console.log(trap([4,2,0,3,2,5])); // 9

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

15. Serialize and Deserialize Binary Tree

Problem: Design an algorithm to serialize and deserialize a binary tree.

/**
 * Definition for a binary tree node.
 */
function TreeNode(val, left, right) {
  this.val = (val === undefined ? 0 : val);
  this.left = (left === undefined ? null : left);
  this.right = (right === undefined ? null : right);
}

/**
 * Encodes a tree to a single string.
 * @param {TreeNode} root
 * @return {string}
 */
function serialize(root) {
  const result = [];

  function preorder(node) {
    if (!node) {
      result.push('null');
      return;
    }

    result.push(node.val.toString());
    preorder(node.left);
    preorder(node.right);
  }

  preorder(root);
  return result.join(',');
}

/**
 * Decodes your encoded data to tree.
 * @param {string} data
 * @return {TreeNode}
 */
function deserialize(data) {
  const values = data.split(',');
  let index = 0;

  function buildTree() {
    if (index >= values.length || values[index] === 'null') {
      index++;
      return null;
    }

    const node = new TreeNode(parseInt(values[index]));
    index++;
    node.left = buildTree();
    node.right = buildTree();

    return node;
  }

  return buildTree();
}

// Test cases
const root = new TreeNode(1,
  new TreeNode(2),
  new TreeNode(3,
    new TreeNode(4),
    new TreeNode(5)
  )
);

const serialized = serialize(root);
console.log(serialized); // "1,2,null,null,3,4,null,null,5,null,null"

const deserialized = deserialize(serialized);
console.log(serialize(deserialized)); // "1,2,null,null,3,4,null,null,5,null,null"

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

Array Manipulation

16. Rotate Array

Problem: Rotate an array to the right by k steps.

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {void} Do not return anything, modify nums in-place instead.
 */
function rotate(nums, k) {
  k = k % nums.length;

  // Reverse entire array
  reverse(nums, 0, nums.length - 1);
  // Reverse first k elements
  reverse(nums, 0, k - 1);
  // Reverse remaining elements
  reverse(nums, k, nums.length - 1);
}

function reverse(nums, start, end) {
  while (start < end) {
    [nums[start], nums[end]] = [nums[end], nums[start]];
    start++;
    end--;
  }
}

// Test cases
const arr1 = [1,2,3,4,5,6,7];
rotate(arr1, 3);
console.log(arr1); // [5,6,7,1,2,3,4]

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

17. Find All Numbers Disappeared in an Array

Problem: Find all numbers that disappeared in an array.

/**
 * @param {number[]} nums
 * @return {number[]}
 */
function findDisappearedNumbers(nums) {
  const result = [];

  for (let i = 0; i < nums.length; i++) {
    const index = Math.abs(nums[i]) - 1;
    if (nums[index] > 0) {
      nums[index] = -nums[index];
    }
  }

  for (let i = 0; i < nums.length; i++) {
    if (nums[i] > 0) {
      result.push(i + 1);
    }
  }

  return result;
}

// Test cases
console.log(findDisappearedNumbers([4,3,2,7,8,2,3,1])); // [5,6]
console.log(findDisappearedNumbers([1,1])); // [2]

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

18. Product of Array Except Self

Problem: Return an array where each element is the product of all elements except itself.

/**
 * @param {number[]} nums
 * @return {number[]}
 */
function productExceptSelf(nums) {
  const n = nums.length;
  const result = new Array(n).fill(1);

  // Calculate left products
  let leftProduct = 1;
  for (let i = 0; i < n; i++) {
    result[i] = leftProduct;
    leftProduct *= nums[i];
  }

  // Calculate right products and multiply with left products
  let rightProduct = 1;
  for (let i = n - 1; i >= 0; i--) {
    result[i] *= rightProduct;
    rightProduct *= nums[i];
  }

  return result;
}

// Test cases
console.log(productExceptSelf([1,2,3,4])); // [24,12,8,6]
console.log(productExceptSelf([-1,1,0,-3,3])); // [0,0,9,0,0]

// Time Complexity: O(n)
// Space Complexity: O(1) (excluding output array)
Enter fullscreen mode Exit fullscreen mode

19. Find Minimum in Rotated Sorted Array

Problem: Find the minimum element in a rotated sorted array.

/**
 * @param {number[]} nums
 * @return {number}
 */
function findMin(nums) {
  let left = 0;
  let right = nums.length - 1;

  while (left < right) {
    const mid = Math.floor((left + right) / 2);

    if (nums[mid] > nums[right]) {
      left = mid + 1;
    } else {
      right = mid;
    }
  }

  return nums[left];
}

// Test cases
console.log(findMin([3,4,5,1,2])); // 1
console.log(findMin([4,5,6,7,0,1,2])); // 0
console.log(findMin([11,13,15,17])); // 11

// Time Complexity: O(log n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

20. Search in Rotated Sorted Array

Problem: Search in a rotated sorted array.

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
function search(nums, target) {
  let left = 0;
  let right = nums.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (nums[mid] === target) {
      return mid;
    }

    // Check which half is sorted
    if (nums[left] <= nums[mid]) {
      // Left half is sorted
      if (nums[left] <= target && target < nums[mid]) {
        right = mid - 1;
      } else {
        left = mid + 1;
      }
    } else {
      // Right half is sorted
      if (nums[mid] < target && target <= nums[right]) {
        left = mid + 1;
      } else {
        right = mid - 1;
      }
    }
  }

  return -1;
}

// Test cases
console.log(search([4,5,6,7,0,1,2], 0)); // 4
console.log(search([4,5,6,7,0,1,2], 3)); // -1
console.log(search([1], 0)); // -1

// Time Complexity: O(log n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

String Manipulation

21. Longest Common Prefix

Problem: Find the longest common prefix string amongst an array of strings.

/**
 * @param {string[]} strs
 * @return {string}
 */
function longestCommonPrefix(strs) {
  if (strs.length === 0) return "";

  let prefix = strs[0];

  for (let i = 1; i < strs.length; i++) {
    while (strs[i].indexOf(prefix) !== 0) {
      prefix = prefix.substring(0, prefix.length - 1);
      if (prefix === "") return "";
    }
  }

  return prefix;
}

// Test cases
console.log(longestCommonPrefix(["flower","flow","flight"])); // "fl"
console.log(longestCommonPrefix(["dog","racecar","car"])); // ""

// Time Complexity: O(n * m) where n is number of strings and m is min string length
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

22. Valid Anagram

Problem: Check if two strings are anagrams of each other.

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
function isAnagram(s, t) {
  if (s.length !== t.length) return false;

  const charCount = {};

  for (const char of s) {
    charCount[char] = (charCount[char] || 0) + 1;
  }

  for (const char of t) {
    if (!charCount[char]) return false;
    charCount[char]--;
  }

  return true;
}

// Alternative: Using sorting
function isAnagramSorted(s, t) {
  return s.split('').sort().join('') === t.split('').sort().join('');
}

// Test cases
console.log(isAnagram("anagram", "nagaram")); // true
console.log(isAnagram("rat", "car")); // false

// Time Complexity: O(n)
// Space Complexity: O(1) (assuming fixed character set)
Enter fullscreen mode Exit fullscreen mode

23. String to Integer (atoi)

Problem: Implement atoi to convert a string to an integer.

/**
 * @param {string} s
 * @return {number}
 */
function myAtoi(s) {
  s = s.trim();

  if (s.length === 0) return 0;

  let sign = 1;
  let result = 0;
  let i = 0;

  // Check for sign
  if (s[0] === '-' || s[0] === '+') {
    sign = s[0] === '-' ? -1 : 1;
    i++;
  }

  // Convert digits
  while (i < s.length && /\d/.test(s[i])) {
    const digit = parseInt(s[i]);

    // Check for overflow
    if (result > (Math.pow(2, 31) - 1) / 10 || 
        (result === Math.floor((Math.pow(2, 31) - 1) / 10) && digit > 7)) {
      return sign === 1 ? Math.pow(2, 31) - 1 : -Math.pow(2, 31);
    }

    result = result * 10 + digit;
    i++;
  }

  return sign * result;
}

// Test cases
console.log(myAtoi("42")); // 42
console.log(myAtoi("   -42")); // -42
console.log(myAtoi("4193 with words")); // 4193
console.log(myAtoi("words and 987")); // 0

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

24. Implement strStr()

Problem: Return the index of the first occurrence of needle in haystack.

/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
function strStr(haystack, needle) {
  if (needle === "") return 0;
  if (haystack.length < needle.length) return -1;

  for (let i = 0; i <= haystack.length - needle.length; i++) {
    if (haystack.substring(i, i + needle.length) === needle) {
      return i;
    }
  }

  return -1;
}

// Test cases
console.log(strStr("hello", "ll")); // 2
console.log(strStr("aaaaa", "bba")); // -1
console.log(strStr("", "")); // 0

// Time Complexity: O(n * m)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

25. Count and Say

Problem: Generate the nth term of the count-and-say sequence.

/**
 * @param {number} n
 * @return {string}
 */
function countAndSay(n) {
  if (n === 1) return "1";

  let prev = countAndSay(n - 1);
  let result = "";
  let count = 1;

  for (let i = 1; i < prev.length; i++) {
    if (prev[i] === prev[i - 1]) {
      count++;
    } else {
      result += count + prev[i - 1];
      count = 1;
    }
  }

  result += count + prev[prev.length - 1];
  return result;
}

// Test cases
console.log(countAndSay(1)); // "1"
console.log(countAndSay(4)); // "1211"

// Time Complexity: O(2^n)
// Space Complexity: O(2^n)
Enter fullscreen mode Exit fullscreen mode

Object & Data Structures

26. Deep Clone Object

Problem: Create a deep clone of an object.

/**
 * @param {any} obj
 * @return {any}
 */
function deepClone(obj) {
  // Handle primitives and null
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // Handle Date
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }

  // Handle Array
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item));
  }

  // Handle Object
  const clonedObj = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      clonedObj[key] = deepClone(obj[key]);
    }
  }

  return clonedObj;
}

// Test cases
const original = {
  name: "John",
  age: 30,
  hobbies: ["reading", "coding"],
  address: {
    city: "New York",
    country: "USA"
  }
};

const cloned = deepClone(original);
cloned.name = "Jane";
cloned.hobbies.push("gaming");

console.log(original.name); // "John"
console.log(cloned.name); // "Jane"
console.log(original.hobbies); // ["reading", "coding"]
console.log(cloned.hobbies); // ["reading", "coding", "gaming"]

// Time Complexity: O(n) where n is total number of properties
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

27. Object Deep Merge

Problem: Deep merge two objects.

/**
 * @param {Object} target
 * @param {Object} source
 * @return {Object}
 */
function deepMerge(target, source) {
  const result = { ...target };

  for (const key in source) {
    if (source.hasOwnProperty(key)) {
      if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
        result[key] = deepMerge(result[key] || {}, source[key]);
      } else {
        result[key] = source[key];
      }
    }
  }

  return result;
}

// Test cases
const obj1 = {
  a: 1,
  b: {
    x: 10,
    y: 20
  }
};

const obj2 = {
  b: {
    y: 30,
    z: 40
  },
  c: 3
};

const merged = deepMerge(obj1, obj2);
console.log(merged);
// { a: 1, b: { x: 10, y: 30, z: 40 }, c: 3 }

// Time Complexity: O(n) where n is total number of properties
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

28. Implement LRU Cache

Problem: Implement an LRU (Least Recently Used) cache.

class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
  }

  get(key) {
    if (!this.cache.has(key)) {
      return -1;
    }

    // Move to end (most recently used)
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value);

    return value;
  }

  put(key, value) {
    // If key exists, delete it first
    if (this.cache.has(key)) {
      this.cache.delete(key);
    }

    // Add to cache
    this.cache.set(key, value);

    // If over capacity, remove least recently used (first item)
    if (this.cache.size > this.capacity) {
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
  }
}

// Test cases
const cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1)); // 1
cache.put(3, 3); // evicts key 2
console.log(cache.get(2)); // -1
cache.put(4, 4); // evicts key 1
console.log(cache.get(1)); // -1
console.log(cache.get(3)); // 3
console.log(cache.get(4)); // 4

// Time Complexity: O(1) for both get and put
// Space Complexity: O(capacity)
Enter fullscreen mode Exit fullscreen mode

29. Implement Stack using Queues

Problem: Implement a stack using queues.

class StackUsingQueues {
  constructor() {
    this.queue1 = [];
    this.queue2 = [];
  }

  push(x) {
    // Push to queue2
    this.queue2.push(x);

    // Move all elements from queue1 to queue2
    while (this.queue1.length > 0) {
      this.queue2.push(this.queue1.shift());
    }

    // Swap queues
    [this.queue1, this.queue2] = [this.queue2, this.queue1];
  }

  pop() {
    if (this.isEmpty()) {
      throw new Error("Stack is empty");
    }
    return this.queue1.shift();
  }

  top() {
    if (this.isEmpty()) {
      throw new Error("Stack is empty");
    }
    return this.queue1[0];
  }

  isEmpty() {
    return this.queue1.length === 0;
  }
}

// Test cases
const stack = new StackUsingQueues();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.top()); // 3
console.log(stack.pop()); // 3
console.log(stack.top()); // 2

// Time Complexity: O(n) for push, O(1) for pop and top
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

30. Implement Queue using Stacks

Problem: Implement a queue using stacks.

class QueueUsingStacks {
  constructor() {
    this.stack1 = []; // For push
    this.stack2 = []; // For pop
  }

  push(x) {
    this.stack1.push(x);
  }

  pop() {
    if (this.isEmpty()) {
      throw new Error("Queue is empty");
    }

    // If stack2 is empty, move all elements from stack1
    if (this.stack2.length === 0) {
      while (this.stack1.length > 0) {
        this.stack2.push(this.stack1.pop());
      }
    }

    return this.stack2.pop();
  }

  peek() {
    if (this.isEmpty()) {
      throw new Error("Queue is empty");
    }

    if (this.stack2.length === 0) {
      while (this.stack1.length > 0) {
        this.stack2.push(this.stack1.pop());
      }
    }

    return this.stack2[this.stack2.length - 1];
  }

  isEmpty() {
    return this.stack1.length === 0 && this.stack2.length === 0;
  }
}

// Test cases
const queue = new QueueUsingStacks();
queue.push(1);
queue.push(2);
queue.push(3);
console.log(queue.peek()); // 1
console.log(queue.pop()); // 1
console.log(queue.peek()); // 2

// Time Complexity: O(1) amortized for push and pop
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

Recursion & Algorithms

31. Fibonacci Number

Problem: Calculate the nth Fibonacci number.

/**
 * @param {number} n
 * @return {number}
 */
// Recursive (inefficient)
function fibRecursive(n) {
  if (n <= 1) return n;
  return fibRecursive(n - 1) + fibRecursive(n - 2);
}

// Memoization
function fibMemo(n, memo = {}) {
  if (n in memo) return memo[n];
  if (n <= 1) return n;

  memo[n] = fibMemo(n - 1, memo) + fibMemo(n - 2, memo);
  return memo[n];
}

// Iterative (efficient)
function fibIterative(n) {
  if (n <= 1) return n;

  let prev = 0;
  let curr = 1;

  for (let i = 2; i <= n; i++) {
    const next = prev + curr;
    prev = curr;
    curr = next;
  }

  return curr;
}

// Test cases
console.log(fibMemo(10)); // 55
console.log(fibIterative(10)); // 55

// Time Complexity: O(n) for memoization and iterative
// Space Complexity: O(n) for memoization, O(1) for iterative
Enter fullscreen mode Exit fullscreen mode

32. Factorial

Problem: Calculate the factorial of a number.

/**
 * @param {number} n
 * @return {number}
 */
// Recursive
function factorialRecursive(n) {
  if (n <= 1) return 1;
  return n * factorialRecursive(n - 1);
}

// Iterative
function factorialIterative(n) {
  let result = 1;
  for (let i = 2; i <= n; i++) {
    result *= i;
  }
  return result;
}

// Test cases
console.log(factorialRecursive(5)); // 120
console.log(factorialIterative(5)); // 120

// Time Complexity: O(n)
// Space Complexity: O(n) for recursive, O(1) for iterative
Enter fullscreen mode Exit fullscreen mode

33. Power Function

Problem: Implement pow(x, n).

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
function myPow(x, n) {
  if (n === 0) return 1;
  if (n < 0) {
    x = 1 / x;
    n = -n;
  }

  let result = 1;
  let currentProduct = x;

  while (n > 0) {
    if (n % 2 === 1) {
      result *= currentProduct;
    }
    currentProduct *= currentProduct;
    n = Math.floor(n / 2);
  }

  return result;
}

// Test cases
console.log(myPow(2, 10)); // 1024
console.log(myPow(2.1, 3)); // 9.261
console.log(myPow(2, -2)); // 0.25

// Time Complexity: O(log n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

34. Generate Parentheses

Problem: Generate all combinations of well-formed parentheses.

/**
 * @param {number} n
 * @return {string[]}
 */
function generateParenthesis(n) {
  const result = [];

  function backtrack(current, open, close) {
    if (current.length === 2 * n) {
      result.push(current);
      return;
    }

    if (open < n) {
      backtrack(current + '(', open + 1, close);
    }

    if (close < open) {
      backtrack(current + ')', open, close + 1);
    }
  }

  backtrack('', 0, 0);
  return result;
}

// Test cases
console.log(generateParenthesis(3)); 
// ["((()))","(()())","(())()","()(())","()()()"]

// Time Complexity: O(4^n / sqrt(n))
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

35. Permutations

Problem: Generate all permutations of an array.

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
function permute(nums) {
  const result = [];

  function backtrack(start) {
    if (start === nums.length) {
      result.push([...nums]);
      return;
    }

    for (let i = start; i < nums.length; i++) {
      // Swap
      [nums[start], nums[i]] = [nums[i], nums[start]];

      // Recurse
      backtrack(start + 1);

      // Backtrack
      [nums[start], nums[i]] = [nums[i], nums[start]];
    }
  }

  backtrack(0);
  return result;
}

// Test cases
console.log(permute([1, 2, 3]));
// [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

// Time Complexity: O(n! * n)
// Space Complexity: O(n! * n)
Enter fullscreen mode Exit fullscreen mode

Functional Programming

36. Array Map Implementation

Problem: Implement the map function.

/**
 * @param {Array} array
 * @param {Function} callback
 * @return {Array}
 */
function map(array, callback) {
  const result = [];

  for (let i = 0; i < array.length; i++) {
    result.push(callback(array[i], i, array));
  }

  return result;
}

// Test cases
const numbers = [1, 2, 3, 4, 5];
console.log(map(numbers, x => x * 2)); // [2, 4, 6, 8, 10]
console.log(map(numbers, (x, i) => x + i)); // [1, 3, 5, 7, 9]

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

37. Array Filter Implementation

Problem: Implement the filter function.

/**
 * @param {Array} array
 * @param {Function} callback
 * @return {Array}
 */
function filter(array, callback) {
  const result = [];

  for (let i = 0; i < array.length; i++) {
    if (callback(array[i], i, array)) {
      result.push(array[i]);
    }
  }

  return result;
}

// Test cases
const numbers = [1, 2, 3, 4, 5, 6];
console.log(filter(numbers, x => x % 2 === 0)); // [2, 4, 6]
console.log(filter(numbers, (x, i) => x > i)); // [1, 2, 3, 4, 5]

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

38. Array Reduce Implementation

Problem: Implement the reduce function.

/**
 * @param {Array} array
 * @param {Function} callback
 * @param {*} initialValue
 * @return {*}
 */
function reduce(array, callback, initialValue) {
  let accumulator = initialValue;
  let startIndex = 0;

  if (initialValue === undefined) {
    accumulator = array[0];
    startIndex = 1;
  }

  for (let i = startIndex; i < array.length; i++) {
    accumulator = callback(accumulator, array[i], i, array);
  }

  return accumulator;
}

// Test cases
const numbers = [1, 2, 3, 4, 5];
console.log(reduce(numbers, (sum, x) => sum + x, 0)); // 15
console.log(reduce(numbers, (product, x) => product * x, 1)); // 120
console.log(reduce(['a', 'b', 'c'], (result, char) => result + char, '')); // "abc"

// Time Complexity: O(n)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

39. Currying Function

Problem: Implement function currying.

/**
 * @param {Function} fn
 * @return {Function}
 */
function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    }

    return function(...moreArgs) {
      return curried.apply(this, [...args, ...moreArgs]);
    };
  };
}

// Test cases
function add(a, b, c) {
  return a + b + c;
}

const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2, 3)); // 6

// Time Complexity: Depends on the function being curried
// Space Complexity: O(n) where n is number of arguments
Enter fullscreen mode Exit fullscreen mode

40. Memoization Function

Problem: Implement a memoization function.

/**
 * @param {Function} fn
 * @return {Function}
 */
function memoize(fn) {
  const cache = new Map();

  return function(...args) {
    const key = JSON.stringify(args);

    if (cache.has(key)) {
      return cache.get(key);
    }

    const result = fn.apply(this, args);
    cache.set(key, result);

    return result;
  };
}

// Test cases
function expensiveFunction(x) {
  console.log("Computing...");
  return x * 2;
}

const memoizedExpensive = memoize(expensiveFunction);
console.log(memoizedExpensive(5)); // "Computing..." then 10
console.log(memoizedExpensive(5)); // 10 (cached)
console.log(memoizedExpensive(10)); // "Computing..." then 20

// Time Complexity: O(1) for cached results, O(n) for first computation
// Space Complexity: O(n) where n is number of unique argument combinations
Enter fullscreen mode Exit fullscreen mode

Async & Promises

41. Promise.all Implementation

Problem: Implement Promise.all.

/**
 * @param {Promise[]} promises
 * @return {Promise}
 */
function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      resolve([]);
      return;
    }

    const results = new Array(promises.length);
    let completed = 0;

    promises.forEach((promise, index) => {
      Promise.resolve(promise)
        .then(value => {
          results[index] = value;
          completed++;

          if (completed === promises.length) {
            resolve(results);
          }
        })
        .catch(error => {
          reject(error);
        });
    });
  });
}

// Test cases
const promise1 = Promise.resolve(3);
const promise2 = 1337;
const promise3 = new Promise((resolve) => {
  setTimeout(() => resolve("foo"), 100);
});

promiseAll([promise1, promise2, promise3])
  .then(values => console.log(values)); // [3, 1337, "foo"]

// Time Complexity: O(n) where n is number of promises
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

42. Promise.race Implementation

Problem: Implement Promise.race.

/**
 * @param {Promise[]} promises
 * @return {Promise}
 */
function promiseRace(promises) {
  return new Promise((resolve, reject) => {
    if (promises.length === 0) {
      // Never resolves
      return;
    }

    promises.forEach(promise => {
      Promise.resolve(promise)
        .then(resolve)
        .catch(reject);
    });
  });
}

// Test cases
const promise1 = new Promise(resolve => setTimeout(() => resolve('one'), 500));
const promise2 = new Promise(resolve => setTimeout(() => resolve('two'), 100));

promiseRace([promise1, promise2])
  .then(value => console.log(value)); // "two"

// Time Complexity: O(1) (returns as soon as first promise settles)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

43. Async/Await Parallel Execution

Problem: Execute async operations in parallel with concurrency limit.

/**
 * @param {Array<Function>} tasks
 * @param {number} concurrency
 * @return {Promise<Array>}
 */
async function parallel(tasks, concurrency = Infinity) {
  const results = [];
  const executing = [];

  for (const task of tasks) {
    const promise = task().then(result => {
      results.push(result);
    });

    executing.push(promise);

    if (executing.length >= concurrency) {
      await Promise.race(executing);
    }
  }

  await Promise.all(executing);
  return results;
}

// Test cases
const tasks = [
  () => new Promise(resolve => setTimeout(() => resolve(1), 100)),
  () => new Promise(resolve => setTimeout(() => resolve(2), 200)),
  () => new Promise(resolve => setTimeout(() => resolve(3), 300)),
  () => new Promise(resolve => setTimeout(() => resolve(4), 400)),
  () => new Promise(resolve => setTimeout(() => resolve(5), 500))
];

parallel(tasks, 2).then(results => console.log(results)); // [1, 2, 3, 4, 5]

// Time Complexity: O(n) where n is number of tasks
// Space Complexity: O(concurrency)
Enter fullscreen mode Exit fullscreen mode

44. Retry Function

Problem: Implement a retry function for async operations.

/**
 * @param {Function} fn
 * @param {Object} options
 * @return {Promise}
 */
async function retry(fn, options = {}) {
  const {
    maxAttempts = 3,
    delay = 1000,
    backoff = 2
  } = options;

  let lastError;

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;

      if (attempt < maxAttempts) {
        const waitTime = delay * Math.pow(backoff, attempt - 1);
        console.log(`Attempt ${attempt} failed. Retrying in ${waitTime}ms...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
      }
    }
  }

  throw lastError;
}

// Test cases
let attempts = 0;
const flakyFunction = async () => {
  attempts++;
  if (attempts < 3) {
    throw new Error("Temporary failure");
  }
  return "Success!";
};

retry(flakyFunction, { maxAttempts: 5, delay: 100 })
  .then(result => console.log(result)) // "Success!"
  .catch(error => console.error(error));

// Time Complexity: O(maxAttempts * fnTime)
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

45. Debounce Function

Problem: Implement a debounce function.

/**
 * @param {Function} func
 * @param {number} wait
 * @return {Function}
 */
function debounce(func, wait) {
  let timeout;

  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func.apply(this, args);
    };

    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

// Test cases
const debouncedSearch = debounce((query) => {
  console.log("Searching for:", query);
}, 300);

debouncedSearch("javascript");
debouncedSearch("javascript tutorial");
debouncedSearch("javascript tutorial examples");
// After 300ms: "Searching for: javascript tutorial examples"

// Time Complexity: O(1) for each call
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

DOM & Browser APIs

46. Event Delegation

Problem: Implement event delegation for dynamic elements.

/**
 * @param {HTMLElement} parent
 * @param {string} eventType
 * @param {string} selector
 * @param {Function} handler
 */
function delegateEvent(parent, eventType, selector, handler) {
  parent.addEventListener(eventType, function(event) {
    const target = event.target.closest(selector);

    if (target && parent.contains(target)) {
      handler.call(target, event);
    }
  });
}

// Test case
// HTML: <ul id="list"><li>Item 1</li><li>Item 2</li></ul>
const list = document.getElementById('list');

delegateEvent(list, 'click', 'li', function(event) {
  console.log('Clicked:', this.textContent);
  // Dynamically add new item
  const newItem = document.createElement('li');
  newItem.textContent = `Item ${list.children.length + 1}`;
  list.appendChild(newItem);
});

// Time Complexity: O(1) per event
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

47. Custom DOM Element Creator

Problem: Create a helper function to build DOM elements.

/**
 * @param {string} tag
 * @param {Object} attributes
 * @param {Array} children
 * @return {HTMLElement}
 */
function createElement(tag, attributes = {}, children = []) {
  const element = document.createElement(tag);

  // Set attributes
  for (const [key, value] of Object.entries(attributes)) {
    if (key === 'className') {
      element.className = value;
    } else if (key === 'style' && typeof value === 'object') {
      Object.assign(element.style, value);
    } else if (key.startsWith('on') && typeof value === 'function') {
      element.addEventListener(key.slice(2).toLowerCase(), value);
    } else {
      element.setAttribute(key, value);
    }
  }

  // Add children
  children.forEach(child => {
    if (typeof child === 'string') {
      element.appendChild(document.createTextNode(child));
    } else if (child instanceof HTMLElement) {
      element.appendChild(child);
    } else if (Array.isArray(child)) {
      child.forEach(c => element.appendChild(c));
    }
  });

  return element;
}

// Test cases
const button = createElement('button', {
  className: 'btn btn-primary',
  onclick: () => console.log('Clicked!')
}, ['Click Me']);

document.body.appendChild(button);

const card = createElement('div', {
  className: 'card',
  style: { padding: '20px', background: '#f0f0f0' }
}, [
  createElement('h2', {}, ['Card Title']),
  createElement('p', {}, ['Card content goes here...']),
  createElement('button', { className: 'btn' }, ['Action'])
]);

document.body.appendChild(card);

// Time Complexity: O(n) where n is number of children
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

48. Local Storage Wrapper

Problem: Create a type-safe local storage wrapper.

class Storage {
  constructor(prefix = 'app_') {
    this.prefix = prefix;
  }

  set(key, value) {
    try {
      const serialized = JSON.stringify(value);
      localStorage.setItem(this.prefix + key, serialized);
      return true;
    } catch (error) {
      console.error('Storage set error:', error);
      return false;
    }
  }

  get(key, defaultValue = null) {
    try {
      const item = localStorage.getItem(this.prefix + key);
      return item ? JSON.parse(item) : defaultValue;
    } catch (error) {
      console.error('Storage get error:', error);
      return defaultValue;
    }
  }

  remove(key) {
    localStorage.removeItem(this.prefix + key);
  }

  clear() {
    const keys = Object.keys(localStorage);
    keys.forEach(key => {
      if (key.startsWith(this.prefix)) {
        localStorage.removeItem(key);
      }
    });
  }

  has(key) {
    return localStorage.getItem(this.prefix + key) !== null;
  }
}

// Test cases
const storage = new Storage('myapp_');
storage.set('user', { name: 'John', age: 30 });
console.log(storage.get('user')); // { name: 'John', age: 30 }
console.log(storage.has('user')); // true
storage.remove('user');
console.log(storage.has('user')); // false

// Time Complexity: O(1) for get/set/remove, O(n) for clear
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

49. URL Parameter Parser

Problem: Parse URL parameters into an object.

/**
 * @param {string} url
 * @return {Object}
 */
function parseUrlParams(url) {
  const params = {};
  const queryString = url.split('?')[1];

  if (!queryString) return params;

  queryString.split('&').forEach(param => {
    const [key, value] = param.split('=');
    params[decodeURIComponent(key)] = decodeURIComponent(value || '');
  });

  return params;
}

// Test cases
console.log(parseUrlParams('https://example.com?name=John&age=30'));
// { name: 'John', age: '30' }

console.log(parseUrlParams('https://example.com?search=hello%20world&page=1'));
// { search: 'hello world', page: '1' }

console.log(parseUrlParams('https://example.com'));
// {}

// Time Complexity: O(n) where n is number of parameters
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

50. Cookie Manager

Problem: Create a cookie management utility.

class CookieManager {
  set(name, value, days = 7) {
    const expires = new Date();
    expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);

    document.cookie = `${name}=${encodeURIComponent(value)};expires=${expires.toUTCString()};path=/`;
  }

  get(name) {
    const nameEQ = name + '=';
    const cookies = document.cookie.split(';');

    for (let i = 0; i < cookies.length; i++) {
      let cookie = cookies[i].trim();
      if (cookie.indexOf(nameEQ) === 0) {
        return decodeURIComponent(cookie.substring(nameEQ.length));
      }
    }

    return null;
  }

  remove(name) {
    this.set(name, '', -1);
  }

  getAll() {
    const cookies = {};
    document.cookie.split(';').forEach(cookie => {
      const [name, value] = cookie.trim().split('=');
      if (name) {
        cookies[name] = decodeURIComponent(value || '');
      }
    });
    return cookies;
  }
}

// Test cases
const cookies = new CookieManager();
cookies.set('username', 'john_doe', 30);
cookies.set('theme', 'dark', 7);

console.log(cookies.get('username')); // 'john_doe'
console.log(cookies.getAll()); // { username: 'john_doe', theme: 'dark' }

cookies.remove('username');
console.log(cookies.get('username')); // null

// Time Complexity: O(n) for get and getAll where n is number of cookies
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

Additional Practice Problems

51. Flatten Nested Array

Problem: Flatten a nested array structure.

/**
 * @param {Array} arr
 * @return {Array}
 */
function flatten(arr) {
  const result = [];

  function flattenHelper(item) {
    if (Array.isArray(item)) {
      item.forEach(flattenHelper);
    } else {
      result.push(item);
    }
  }

  flattenHelper(arr);
  return result;
}

// Alternative: Using reduce
function flattenReduce(arr) {
  return arr.reduce((acc, item) => {
    return acc.concat(Array.isArray(item) ? flattenReduce(item) : item);
  }, []);
}

// Test cases
console.log(flatten([1, [2, [3, [4, 5]]]])); // [1, 2, 3, 4, 5]
console.log(flattenReduce([1, [2, [3, [4, 5]]]])); // [1, 2, 3, 4, 5]

// Time Complexity: O(n) where n is total number of elements
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

52. Deep Equality Check

Problem: Check if two objects are deeply equal.

/**
 * @param {*} a
 * @param {*} b
 * @return {boolean}
 */
function deepEqual(a, b) {
  // Check for strict equality
  if (a === b) return true;

  // Check for null/undefined
  if (a == null || b == null) return false;

  // Check types
  if (typeof a !== typeof b) return false;

  // Handle arrays
  if (Array.isArray(a)) {
    if (a.length !== b.length) return false;
    for (let i = 0; i < a.length; i++) {
      if (!deepEqual(a[i], b[i])) return false;
    }
    return true;
  }

  // Handle objects
  if (typeof a === 'object') {
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);

    if (keysA.length !== keysB.length) return false;

    for (const key of keysA) {
      if (!keysB.includes(key) || !deepEqual(a[key], b[key])) {
        return false;
      }
    }
    return true;
  }

  return false;
}

// Test cases
console.log(deepEqual({ a: 1, b: 2 }, { a: 1, b: 2 })); // true
console.log(deepEqual({ a: 1, b: 2 }, { a: 1, b: 3 })); // false
console.log(deepEqual([1, 2, 3], [1, 2, 3])); // true
console.log(deepEqual([1, 2, 3], [1, 2, 4])); // false

// Time Complexity: O(n) where n is total number of properties
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

53. Throttle Function

Problem: Implement a throttle function.

/**
 * @param {Function} func
 * @param {number} limit
 * @return {Function}
 */
function throttle(func, limit) {
  let inThrottle;

  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

// Test case
const throttledScroll = throttle(() => {
  console.log('Scroll event handled');
}, 100);

window.addEventListener('scroll', throttledScroll);

// Time Complexity: O(1) per call
// Space Complexity: O(1)
Enter fullscreen mode Exit fullscreen mode

54. Chunk Array

Problem: Split an array into chunks of specified size.

/**
 * @param {Array} array
 * @param {number} size
 * @return {Array}
 */
function chunk(array, size) {
  const result = [];

  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size));
  }

  return result;
}

// Test cases
console.log(chunk([1, 2, 3, 4, 5], 2)); // [[1, 2], [3, 4], [5]]
console.log(chunk([1, 2, 3, 4, 5], 3)); // [[1, 2, 3], [4, 5]]

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

55. Unique Array

Problem: Remove duplicates from an array.

/**
 * @param {Array} array
 * @return {Array}
 */
function unique(array) {
  return [...new Set(array)];
}

// Alternative: Using filter
function uniqueFilter(array) {
  return array.filter((item, index) => array.indexOf(item) === index);
}

// Alternative: Using reduce
function uniqueReduce(array) {
  return array.reduce((acc, item) => {
    if (!acc.includes(item)) {
      acc.push(item);
    }
    return acc;
  }, []);
}

// Test cases
console.log(unique([1, 2, 2, 3, 4, 4, 5])); // [1, 2, 3, 4, 5]
console.log(uniqueFilter(['a', 'b', 'a', 'c'])); // ['a', 'b', 'c']

// Time Complexity: O(n)
// Space Complexity: O(n)
Enter fullscreen mode Exit fullscreen mode

Tips for Practice

1. Understand the Problem

  • Read the problem carefully
  • Identify input/output requirements
  • Consider edge cases

2. Plan Your Approach

  • Start with brute force solution
  • Identify optimization opportunities
  • Consider time and space complexity

3. Implement Incrementally

  • Start with basic functionality
  • Add error handling
  • Test with various inputs

4. Test Thoroughly

  • Test with normal cases
  • Test with edge cases
  • Test with invalid inputs

5. Optimize

  • Look for redundant operations
  • Consider alternative data structures
  • Balance time vs space complexity

Common Time Complexities

  • O(1): Constant time
  • O(log n): Logarithmic time
  • O(n): Linear time
  • O(n log n): Linearithmic time
  • O(n²): Quadratic time
  • O(2ⁿ): Exponential time

Common Space Complexities

  • O(1): Constant space
  • O(n): Linear space
  • O(n²): Quadratic space

Additional Resources

Practice Platforms

Learning Resources

Interview Preparation

  • Cracking the Coding Interview
  • Elements of Programming Interviews
  • Grokking the Coding Interview

Remember: Practice consistently and focus on understanding concepts rather than memorizing solutions!

Top comments (0)