VOOZH about

URL: https://dev.to/mahendranath_reddy_bandi/javascript-practice-coding-examples-interview-guidance-for-problems-5clm

⇱ JavaScript Practice Coding Examples - Interview Guidance for Problems - DEV Community


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)

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)

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)

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)

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)

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

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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

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

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)

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)

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)

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)

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)

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)

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

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

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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)

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!