Skip to content
Go back

Blind75 leetcode

Published:  at  11:06 AM

Blind 75 LeetCode Problems

A comprehensive collection of 75 essential LeetCode problems for coding interviews, organized by category with JavaScript solutions and test cases.

Progress Tracking

CategoryProblemsProgress
Array100/10
Binary50/5
Dynamic Programming110/11
Graph80/8
Interval60/6
Linked List60/6
Matrix40/4
String100/10
Tree130/13
Heap20/2
Total750/75

Quick Reference

#ProblemCategoryDifficultyLeetCode
1Two SumArrayEasyLink
2Contains DuplicateArrayEasyLink
3Best Time to Buy and Sell StockArrayEasyLink
4Product of Array Except SelfArrayMediumLink
5Maximum SubarrayArrayEasyLink
6Maximum Product SubarrayArrayMediumLink
7Search in Rotated Sorted ArrayArrayMediumLink
8Find Minimum in Rotated Sorted ArrayArrayMediumLink
93SumArrayMediumLink
10Container With Most WaterArrayMediumLink

Array Problems (10/10)

Problem 1: Two Sum (Array)

Difficulty: Easy
LeetCode: Link

Description

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice.

JavaScript Solution

/**
 * @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

// Test Case 1
console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]

// Test Case 2
console.log(twoSum([3, 2, 4], 6)); // [1, 2]

// Test Case 3
console.log(twoSum([3, 3], 6)); // [0, 1]

Time Complexity: O(n)
Space Complexity: O(n)


Problem 2: Contains Duplicate (Array)

Difficulty: Easy
LeetCode: Link

Description

Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {boolean}
 */
function containsDuplicate(nums) {
  const set = new Set(nums);
  return set.size !== nums.length;
}

Test Cases

// Test Case 1
console.log(containsDuplicate([1, 2, 3, 1])); // true

// Test Case 2
console.log(containsDuplicate([1, 2, 3, 4])); // false

// Test Case 3
console.log(containsDuplicate([1, 1, 1, 3, 3, 4, 3, 2, 4, 2])); // true

Time Complexity: O(n)
Space Complexity: O(n)


Problem 3: Best Time to Buy and Sell Stock (Array)

Difficulty: Easy
LeetCode: Link

Description

You are given an array prices where prices[i] is the price of a given stock on the ith day. Find the maximum profit you can achieve. You may complete at most one transaction.

JavaScript Solution

/**
 * @param {number[]} prices
 * @return {number}
 */
function maxProfit(prices) {
  let minPrice = Infinity;
  let maxProfit = 0;

  for (const price of prices) {
    minPrice = Math.min(minPrice, price);
    maxProfit = Math.max(maxProfit, price - minPrice);
  }

  return maxProfit;
}

Test Cases

// Test Case 1
console.log(maxProfit([7, 1, 5, 3, 6, 4])); // 5

// Test Case 2
console.log(maxProfit([7, 6, 4, 3, 1])); // 0

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

Time Complexity: O(n)
Space Complexity: O(1)


Problem 4: Product of Array Except Self (Array)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all elements of nums except nums[i]. The solution must be O(n) time and without division.

JavaScript Solution

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

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

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

  return result;
}

Test Cases

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

// Test Case 2
console.log(productExceptSelf([-1, 1, 0, -3, 3])); // [0, 0, 9, 0, 0]

// Test Case 3
console.log(productExceptSelf([1, 2, 3, 4, 5])); // [120, 60, 40, 30, 24]

Time Complexity: O(n)
Space Complexity: O(1) (excluding output array)


Problem 5: Maximum Subarray (Array)

Difficulty: Easy
LeetCode: Link

Description

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

JavaScript Solution

/**
 * @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

// Test Case 1
console.log(maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])); // 6

// Test Case 2
console.log(maxSubArray([1])); // 1

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

Time Complexity: O(n)
Space Complexity: O(1)


Problem 6: Maximum Product Subarray (Array)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums, find a contiguous subarray that has the largest product, and return the product.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number}
 */
function maxProduct(nums) {
  let maxSoFar = nums[0];
  let minSoFar = nums[0];
  let result = nums[0];

  for (let i = 1; i < nums.length; i++) {
    const current = nums[i];
    const temp = maxSoFar;

    maxSoFar = Math.max(current, current * maxSoFar, current * minSoFar);
    minSoFar = Math.min(current, current * temp, current * minSoFar);

    result = Math.max(result, maxSoFar);
  }

  return result;
}

Test Cases

// Test Case 1
console.log(maxProduct([2, 3, -2, 4])); // 6

// Test Case 2
console.log(maxProduct([-2, 0, -1])); // 0

// Test Case 3
console.log(maxProduct([-2, 3, -4])); // 24

Time Complexity: O(n)
Space Complexity: O(1)


Problem 7: Search in Rotated Sorted Array (Array)

Difficulty: Medium
LeetCode: Link

Description

Given the sorted array nums that is rotated at an unknown pivot, and a target value, return the index if found, otherwise -1.

JavaScript Solution

/**
 * @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;
    }

    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

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

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

// Test Case 3
console.log(search([1], 0)); // -1

Time Complexity: O(log n)
Space Complexity: O(1)


Problem 8: Find Minimum in Rotated Sorted Array (Array)

Difficulty: Medium
LeetCode: Link

Description

Given the sorted rotated array nums of distinct elements, return the minimum element.

JavaScript Solution

/**
 * @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

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

// Test Case 2
console.log(findMin([4, 5, 6, 7, 0, 1, 2])); // 0

// Test Case 3
console.log(findMin([11, 13, 15, 17])); // 11

Time Complexity: O(log n)
Space Complexity: O(1)


Problem 9: 3Sum (Array)

Difficulty: Medium
LeetCode: Link

Description

Given integer array nums, return all unique triplets [nums[i], nums[j], nums[k]] such that i != j != k and nums[i] + nums[j] + nums[k] == 0.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
function threeSum(nums) {
  nums.sort((a, b) => a - b);
  const result = [];

  for (let i = 0; i < nums.length - 2; i++) {
    if (i > 0 && nums[i] === nums[i - 1]) continue;

    let left = i + 1;
    let right = nums.length - 1;

    while (left < right) {
      const sum = nums[i] + nums[left] + nums[right];

      if (sum === 0) {
        result.push([nums[i], nums[left], nums[right]]);

        while (left < right && nums[left] === nums[left + 1]) left++;
        while (left < right && nums[right] === nums[right - 1]) right--;

        left++;
        right--;
      } else if (sum < 0) {
        left++;
      } else {
        right--;
      }
    }
  }

  return result;
}

Test Cases

// Test Case 1
console.log(threeSum([-1, 0, 1, 2, -1, -4])); // [[-1, -1, 2], [-1, 0, 1]]

// Test Case 2
console.log(threeSum([0, 1, 1])); // []

// Test Case 3
console.log(threeSum([0, 0, 0, 0])); // [[0, 0, 0]]

Time Complexity: O(n^2)
Space Complexity: O(1) (excluding output)


Problem 10: Container With Most Water (Array)

Difficulty: Medium
LeetCode: Link

Description

Given array height where each element represents the height of a vertical line, find two lines that, together with the x-axis, form a container that holds the most water.

JavaScript Solution

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

  while (left < right) {
    const width = right - left;
    const currentHeight = Math.min(height[left], height[right]);
    const currentArea = width * currentHeight;

    maxArea = Math.max(maxArea, currentArea);

    if (height[left] < height[right]) {
      left++;
    } else {
      right--;
    }
  }

  return maxArea;
}

Test Cases

// Test Case 1
console.log(maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7])); // 49

// Test Case 2
console.log(maxArea([1, 1])); // 1

// Test Case 3
console.log(maxArea([4, 3, 2, 1, 4])); // 16

Time Complexity: O(n)
Space Complexity: O(1)


Binary Problems (5/5)

Problem 11: Sum of Two Integers (Binary)

Difficulty: Medium
LeetCode: Link

Description

Given two integers a and b, return the sum of the two integers without using the + operator.

JavaScript Solution

/**
 * @param {number} a
 * @param {number} b
 * @return {number}
 */
function getSum(a, b) {
  while (b !== 0) {
    const carry = a & b;
    a = a ^ b;
    b = carry << 1;
  }
  return a;
}

Test Cases

// Test Case 1
console.log(getSum(1, 2)); // 3

// Test Case 2
console.log(getSum(2, 3)); // 5

// Test Case 3
console.log(getSum(-2, 3)); // 1

Time Complexity: O(1)
Space Complexity: O(1)


Problem 12: Number of 1 Bits (Binary)

Difficulty: Easy
LeetCode: Link

Description

Write a function that takes an unsigned integer and returns the number of ‘1’ bits it has.

JavaScript Solution

/**
 * @param {number} n - a positive integer
 * @return {number}
 */
function hammingWeight(n) {
  let count = 0;
  while (n > 0) {
    count += n & 1;
    n = n >>> 1;
  }
  return count;
}

Test Cases

// Test Case 1
console.log(hammingWeight(11)); // 3 (binary: 1011)

// Test Case 2
console.log(hammingWeight(128)); // 1 (binary: 10000000)

// Test Case 3
console.log(hammingWeight(0)); // 0

Time Complexity: O(log n)
Space Complexity: O(1)


Problem 13: Counting Bits (Binary)

Difficulty: Easy
LeetCode: Link

Description

Given a non-negative integer num, for every number i in the range 0 ≤ i ≤ num, calculate the number of 1’s in their binary representation and return them as an array.

JavaScript Solution

/**
 * @param {number} num
 * @return {number[]}
 */
function countBits(num) {
  const result = new Array(num + 1).fill(0);

  for (let i = 1; i <= num; i++) {
    result[i] = result[i >> 1] + (i & 1);
  }

  return result;
}

Test Cases

// Test Case 1
console.log(countBits(2)); // [0, 1, 1]

// Test Case 2
console.log(countBits(5)); // [0, 1, 1, 2, 1, 2]

// Test Case 3
console.log(countBits(0)); // [0]

Time Complexity: O(n)
Space Complexity: O(n)


Problem 14: Missing Number (Binary)

Difficulty: Easy
LeetCode: Link

Description

Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number}
 */
function missingNumber(nums) {
  let missing = nums.length;

  for (let i = 0; i < nums.length; i++) {
    missing ^= i ^ nums[i];
  }

  return missing;
}

Test Cases

// Test Case 1
console.log(missingNumber([3, 0, 1])); // 2

// Test Case 2
console.log(missingNumber([0, 1])); // 2

// Test Case 3
console.log(missingNumber([9, 6, 4, 2, 3, 5, 7, 0, 1])); // 8

Time Complexity: O(n)
Space Complexity: O(1)


Problem 15: Reverse Bits (Binary)

Difficulty: Easy
LeetCode: Link

Description

Reverse bits of a given 32-bit unsigned integer.

JavaScript Solution

/**
 * @param {number} n - a positive integer
 * @return {number} - a positive integer
 */
function reverseBits(n) {
  let result = 0;

  for (let i = 0; i < 32; i++) {
    result = (result << 1) | (n & 1);
    n = n >>> 1;
  }

  return result >>> 0;
}

Test Cases

// Test Case 1
console.log(reverseBits(0b00000010100101000001111010011100).toString(2)); // reversed binary

// Test Case 2
console.log(reverseBits(0b11111111111111111111111111111101)); // 3221225471

// Test Case 3
console.log(reverseBits(0)); // 0

Time Complexity: O(1)
Space Complexity: O(1)


Dynamic Programming Problems (11/11)

Problem 16: Climbing Stairs (Dynamic Programming)

Difficulty: Easy
LeetCode: Link

Description

You are climbing a staircase. It takes n steps to reach the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

JavaScript Solution

/**
 * @param {number} n
 * @return {number}
 */
function climbStairs(n) {
  if (n <= 2) return n;

  let prev2 = 1;
  let prev1 = 2;

  for (let i = 3; i <= n; i++) {
    const current = prev1 + prev2;
    prev2 = prev1;
    prev1 = current;
  }

  return prev1;
}

Test Cases

// Test Case 1
console.log(climbStairs(2)); // 2

// Test Case 2
console.log(climbStairs(3)); // 3

// Test Case 3
console.log(climbStairs(4)); // 5

Time Complexity: O(n)
Space Complexity: O(1)


Problem 17: Coin Change (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array coins representing coins of different denominations and an integer amount, return the fewest number of coins that you need to make up that amount. If impossible, return -1.

JavaScript Solution

/**
 * @param {number[]} coins
 * @param {number} amount
 * @return {number}
 */
function coinChange(coins, amount) {
  const dp = new Array(amount + 1).fill(Infinity);
  dp[0] = 0;

  for (let i = 1; i <= amount; i++) {
    for (const coin of coins) {
      if (i - coin >= 0) {
        dp[i] = Math.min(dp[i], dp[i - coin] + 1);
      }
    }
  }

  return dp[amount] === Infinity ? -1 : dp[amount];
}

Test Cases

// Test Case 1
console.log(coinChange([1, 2, 5], 11)); // 3 (5+5+1)

// Test Case 2
console.log(coinChange([2], 3)); // -1

// Test Case 3
console.log(coinChange([1], 0)); // 0

Time Complexity: O(amount × coins.length)
Space Complexity: O(amount)


Problem 18: Longest Increasing Subsequence (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums, return the length of the longest strictly increasing subsequence.

JavaScript Solution

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

  for (const num of nums) {
    let left = 0;
    let right = tails.length;

    while (left < right) {
      const mid = Math.floor((left + right) / 2);
      if (tails[mid] < num) {
        left = mid + 1;
      } else {
        right = mid;
      }
    }

    if (left === tails.length) {
      tails.push(num);
    } else {
      tails[left] = num;
    }
  }

  return tails.length;
}

Test Cases

// Test Case 1
console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18])); // 4

// Test Case 2
console.log(lengthOfLIS([0, 1, 0, 3, 2, 3])); // 4

// Test Case 3
console.log(lengthOfLIS([7, 7, 7, 7, 7, 7, 7])); // 1

Time Complexity: O(n log n)
Space Complexity: O(n)


Problem 19: Combination Sum IV (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums and an integer target, return the number of possible combinations that add up to target.

JavaScript Solution

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
function combinationSum4(nums, target) {
  const dp = new Array(target + 1).fill(0);
  dp[0] = 1;

  for (let i = 1; i <= target; i++) {
    for (const num of nums) {
      if (i - num >= 0) {
        dp[i] += dp[i - num];
      }
    }
  }

  return dp[target];
}

Test Cases

// Test Case 1
console.log(combinationSum4([1, 2, 3], 4)); // 7

// Test Case 2
console.log(combinationSum4([2], 3)); // 0

// Test Case 3
console.log(combinationSum4([1], 0)); // 1

Time Complexity: O(target × nums.length)
Space Complexity: O(target)


Problem 20: House Robber (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number}
 */
function rob(nums) {
  if (nums.length === 0) return 0;
  if (nums.length === 1) return nums[0];

  let prev2 = nums[0];
  let prev1 = Math.max(nums[0], nums[1]);

  for (let i = 2; i < nums.length; i++) {
    const current = Math.max(prev1, prev2 + nums[i]);
    prev2 = prev1;
    prev1 = current;
  }

  return prev1;
}

Test Cases

// Test Case 1
console.log(rob([1, 2, 3, 1])); // 4

// Test Case 2
console.log(rob([2, 7, 9, 3, 1])); // 12

// Test Case 3
console.log(rob([2, 1, 1, 2])); // 4

Time Complexity: O(n)
Space Complexity: O(1)


Problem 21: House Robber II (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Houses are arranged in a circle. The first house is the neighbor of the last house. Return the maximum amount of money you can rob.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number}
 */
function robII(nums) {
  if (nums.length === 0) return 0;
  if (nums.length === 1) return nums[0];

  const robRange = (start, end) => {
    let prev2 = 0;
    let prev1 = 0;

    for (let i = start; i < end; i++) {
      const current = Math.max(prev1, prev2 + nums[i]);
      prev2 = prev1;
      prev1 = current;
    }

    return prev1;
  };

  return Math.max(robRange(0, nums.length - 1), robRange(1, nums.length));
}

Test Cases

// Test Case 1
console.log(robII([2, 3, 2])); // 3

// Test Case 2
console.log(robII([1, 2, 3, 1])); // 4

// Test Case 3
console.log(robII([1, 2, 3])); // 3

Time Complexity: O(n)
Space Complexity: O(1)


Problem 22: Decode Ways (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given a string s containing only digits, return the number of ways to decode it.

JavaScript Solution

/**
 * @param {string} s
 * @return {number}
 */
function numDecodings(s) {
  if (s[0] === "0") return 0;

  let prev2 = 1;
  let prev1 = 1;

  for (let i = 1; i < s.length; i++) {
    let current = 0;

    if (s[i] !== "0") {
      current += prev1;
    }

    const twoDigit = parseInt(s.substring(i - 1, i + 1));
    if (twoDigit >= 10 && twoDigit <= 26) {
      current += prev2;
    }

    prev2 = prev1;
    prev1 = current;
  }

  return prev1;
}

Test Cases

// Test Case 1
console.log(numDecodings("12")); // 2

// Test Case 2
console.log(numDecodings("226")); // 3

// Test Case 3
console.log(numDecodings("0")); // 0

Time Complexity: O(n)
Space Complexity: O(1)


Problem 23: Unique Paths (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

There is a robot at the top-left corner of a m x n grid. It can only move down or right. How many possible unique paths to the bottom-right corner?

JavaScript Solution

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
function uniquePaths(m, n) {
  const dp = new Array(n).fill(1);

  for (let i = 1; i < m; i++) {
    for (let j = 1; j < n; j++) {
      dp[j] += dp[j - 1];
    }
  }

  return dp[n - 1];
}

Test Cases

// Test Case 1
console.log(uniquePaths(3, 7)); // 28

// Test Case 2
console.log(uniquePaths(3, 2)); // 3

// Test Case 3
console.log(uniquePaths(1, 1)); // 1

Time Complexity: O(m × n)
Space Complexity: O(n)


Problem 24: Jump Game (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given an array of non-negative integers nums, where nums[i] represents maximum jump length from position i, determine if you can reach the last index.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {boolean}
 */
function canJump(nums) {
  let maxReach = 0;

  for (let i = 0; i < nums.length; i++) {
    if (i > maxReach) return false;
    maxReach = Math.max(maxReach, i + nums[i]);
    if (maxReach >= nums.length - 1) return true;
  }

  return true;
}

Test Cases

// Test Case 1
console.log(canJump([2, 3, 1, 1, 4])); // true

// Test Case 2
console.log(canJump([3, 2, 1, 0, 4])); // false

// Test Case 3
console.log(canJump([0])); // true

Time Complexity: O(n)
Space Complexity: O(1)


Problem 25: Word Break (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.

JavaScript Solution

/**
 * @param {string} s
 * @param {string[]} wordDict
 * @return {boolean}
 */
function wordBreak(s, wordDict) {
  const wordSet = new Set(wordDict);
  const dp = new Array(s.length + 1).fill(false);
  dp[0] = true;

  for (let i = 1; i <= s.length; i++) {
    for (let j = 0; j < i; j++) {
      if (dp[j] && wordSet.has(s.substring(j, i))) {
        dp[i] = true;
        break;
      }
    }
  }

  return dp[s.length];
}

Test Cases

// Test Case 1
console.log(wordBreak("leetcode", ["leet", "code"])); // true

// Test Case 2
console.log(wordBreak("applepenapple", ["apple", "pen"])); // true

// Test Case 3
console.log(wordBreak("catsandog", ["cats", "dog", "sand", "and", "cat"])); // false

Time Complexity: O(n^2)
Space Complexity: O(n)


Problem 26: Longest Common Subsequence (Dynamic Programming)

Difficulty: Medium
LeetCode: Link

Description

Given two strings text1 and text2, return the length of their longest common subsequence.

JavaScript Solution

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
function longestCommonSubsequence(text1, text2) {
  const m = text1.length;
  const n = text2.length;
  const dp = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));

  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (text1[i - 1] === text2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
      } else {
        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
      }
    }
  }

  return dp[m][n];
}

Test Cases

// Test Case 1
console.log(longestCommonSubsequence("abcde", "ace")); // 3

// Test Case 2
console.log(longestCommonSubsequence("abc", "abc")); // 3

// Test Case 3
console.log(longestCommonSubsequence("abc", "def")); // 0

Time Complexity: O(m × n)
Space Complexity: O(m × n)


Graph Problems (8/8)

Problem 27: Clone Graph (Graph)

Difficulty: Medium
LeetCode: Link

Description

Given a reference of a node in a connected undirected graph, return a deep copy (clone) of the graph. Each node contains a value (val) and a list of its neighbors.

JavaScript Solution

/**
 * // Definition for a Node.
 * function Node(val, neighbors) {
 *    this.val = val === undefined ? 0 : val;
 *    this.neighbors = neighbors === undefined ? [] : neighbors;
 * };
 */

/**
 * @param {Node} node
 * @return {Node}
 */
function cloneGraph(node) {
  if (!node) return null;

  const visited = new Map();

  const dfs = originalNode => {
    if (visited.has(originalNode)) {
      return visited.get(originalNode);
    }

    const newNode = new Node(originalNode.val);
    visited.set(originalNode, newNode);

    for (const neighbor of originalNode.neighbors) {
      newNode.neighbors.push(dfs(neighbor));
    }

    return newNode;
  };

  return dfs(node);
}

Test Cases

// Test case setup - simplified structure representation
const adjList = [
  [2, 4],
  [1, 3],
  [2, 4],
  [1, 3],
];
// Note: Actual testing would require building the Node objects
console.log("Clone Graph test requires Node object setup");

Time Complexity: O(V + E)
Space Complexity: O(V)


Problem 28: Course Schedule (Graph)

Difficulty: Medium
LeetCode: Link

Description

There are numCourses courses labeled from 0 to numCourses - 1. prerequisites[i] = [ai, bi] means you must take course bi before ai. Return true if you can finish all courses, otherwise false.

JavaScript Solution

/**
 * @param {number} numCourses
 * @param {number[][]} prerequisites
 * @return {boolean}
 */
function canFinish(numCourses, prerequisites) {
  const graph = new Array(numCourses).fill(0).map(() => []);
  const inDegree = new Array(numCourses).fill(0);

  // Build graph and in-degree
  for (const [course, prereq] of prerequisites) {
    graph[prereq].push(course);
    inDegree[course]++;
  }

  // Queue for courses with no prerequisites
  const queue = [];
  for (let i = 0; i < numCourses; i++) {
    if (inDegree[i] === 0) {
      queue.push(i);
    }
  }

  let completed = 0;
  while (queue.length > 0) {
    const course = queue.shift();
    completed++;

    for (const nextCourse of graph[course]) {
      inDegree[nextCourse]--;
      if (inDegree[nextCourse] === 0) {
        queue.push(nextCourse);
      }
    }
  }

  return completed === numCourses;
}

Test Cases

// Test Case 1
console.log(canFinish(2, [[1, 0]])); // true

// Test Case 2
console.log(
  canFinish(2, [
    [1, 0],
    [0, 1],
  ])
); // false

// Test Case 3
console.log(
  canFinish(5, [
    [1, 0],
    [2, 0],
    [3, 1],
    [3, 2],
  ])
); // true

Time Complexity: O(V + E)
Space Complexity: O(V + E)


Problem 29: Pacific Atlantic Water Flow (Graph)

Difficulty: Medium
LeetCode: Link

Description

Given an m x n matrix of heights, find locations where water can flow to both Pacific and Atlantic oceans. Water can flow from a cell to neighboring cells (horizontally/vertically) if the neighbor’s height is less than or equal.

JavaScript Solution

/**
 * @param {number[][]} matrix
 * @return {number[][]}
 */
function pacificAtlantic(matrix) {
  if (!matrix || matrix.length === 0 || matrix[0].length === 0) return [];

  const rows = matrix.length;
  const cols = matrix[0].length;
  const pacific = new Array(rows)
    .fill(0)
    .map(() => new Array(cols).fill(false));
  const atlantic = new Array(rows)
    .fill(0)
    .map(() => new Array(cols).fill(false));

  const directions = [
    [-1, 0],
    [1, 0],
    [0, -1],
    [0, 1],
  ];

  const dfs = (row, col, visited) => {
    visited[row][col] = true;

    for (const [dr, dc] of directions) {
      const newRow = row + dr;
      const newCol = col + dc;

      if (
        newRow >= 0 &&
        newRow < rows &&
        newCol >= 0 &&
        newCol < cols &&
        !visited[newRow][newCol] &&
        matrix[newRow][newCol] >= matrix[row][col]
      ) {
        dfs(newRow, newCol, visited);
      }
    }
  };

  // Start from Pacific border (top and left)
  for (let col = 0; col < cols; col++) {
    dfs(0, col, pacific);
  }
  for (let row = 0; row < rows; row++) {
    dfs(row, 0, pacific);
  }

  // Start from Atlantic border (bottom and right)
  for (let col = 0; col < cols; col++) {
    dfs(rows - 1, col, atlantic);
  }
  for (let row = 0; row < rows; row++) {
    dfs(row, cols - 1, atlantic);
  }

  // Find cells reachable from both oceans
  const result = [];
  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      if (pacific[row][col] && atlantic[row][col]) {
        result.push([row, col]);
      }
    }
  }

  return result;
}

Test Cases

// Test Case 1
console.log(
  pacificAtlantic([
    [1, 2, 2, 3, 5],
    [3, 2, 3, 4, 4],
    [2, 4, 5, 3, 1],
    [6, 7, 1, 4, 5],
    [5, 1, 1, 2, 4],
  ])
);
// [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

// Test Case 2
console.log(pacificAtlantic([[1]])); // [[0,0]]

// Test Case 3
console.log(
  pacificAtlantic([
    [1, 2, 3],
    [8, 9, 4],
    [7, 6, 5],
  ])
);
// [[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]

Time Complexity: O(m × n)
Space Complexity: O(m × n)


Problem 30: Number of Islands (Graph)

Difficulty: Medium
LeetCode: Link

Description

Given an m x n 2D grid map '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and formed by connecting adjacent lands horizontally or vertically.

JavaScript Solution

/**
 * @param {character[][]} grid
 * @return {number}
 */
function numIslands(grid) {
  if (!grid || grid.length === 0 || grid[0].length === 0) return 0;

  const rows = grid.length;
  const cols = grid[0].length;
  let count = 0;

  const dfs = (row, col) => {
    if (
      row < 0 ||
      row >= rows ||
      col < 0 ||
      col >= cols ||
      grid[row][col] !== "1"
    ) {
      return;
    }

    grid[row][col] = "0"; // Mark as visited

    dfs(row + 1, col);
    dfs(row - 1, col);
    dfs(row, col + 1);
    dfs(row, col - 1);
  };

  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      if (grid[row][col] === "1") {
        count++;
        dfs(row, col);
      }
    }
  }

  return count;
}

Test Cases

// Test Case 1
const grid1 = [
  ["1", "1", "1", "1", "0"],
  ["1", "1", "0", "1", "0"],
  ["1", "1", "0", "0", "0"],
  ["0", "0", "0", "0", "0"],
];
console.log(numIslands(grid1)); // 1

// Test Case 2
const grid2 = [
  ["1", "1", "0", "0", "0"],
  ["1", "1", "0", "0", "0"],
  ["0", "0", "1", "0", "0"],
  ["0", "0", "0", "1", "1"],
];
console.log(numIslands(grid2)); // 3

// Test Case 3
console.log(numIslands([["0"]])); // 0

Time Complexity: O(m × n)
Space Complexity: O(m × n) (due to recursion stack)


Problem 31: Longest Consecutive Sequence (Graph)

Difficulty: Medium
LeetCode: Link

Description

Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.

JavaScript Solution

/**
 * @param {number[]} nums
 * @return {number}
 */
function longestConsecutive(nums) {
  const numSet = new Set(nums);
  let longest = 0;

  for (const num of numSet) {
    // Only start counting from beginning of sequence
    if (!numSet.has(num - 1)) {
      let current = num;
      let length = 1;

      while (numSet.has(current + 1)) {
        current++;
        length++;
      }

      longest = Math.max(longest, length);
    }
  }

  return longest;
}

Test Cases

// Test Case 1
console.log(longestConsecutive([100, 4, 200, 1, 3, 2])); // 4

// Test Case 2
console.log(longestConsecutive([0, 3, 7, 2, 5, 8, 4, 6, 0, 1])); // 9

// Test Case 3
console.log(longestConsecutive([])); // 0

Time Complexity: O(n)
Space Complexity: O(n)


Interval Problems (6/6)

Problem 32: Insert Interval (Interval)

Difficulty: Medium
LeetCode: Link

Description

Given a set of non-overlapping intervals, insert a new interval into intervals (merge if necessary).

JavaScript Solution

/**
 * @param {number[][]} intervals
 * @param {number[]} newInterval
 * @return {number[][]}
 */
function insert(intervals, newInterval) {
  const result = [];
  let i = 0;

  // Add intervals before newInterval
  while (i < intervals.length && intervals[i][1] < newInterval[0]) {
    result.push(intervals[i]);
    i++;
  }

  // Merge overlapping intervals
  while (i < intervals.length && intervals[i][0] <= newInterval[1]) {
    newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
    newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
    i++;
  }
  result.push(newInterval);

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

  return result;
}

Test Cases

// Test Case 1
console.log(
  insert(
    [
      [1, 3],
      [6, 9],
    ],
    [2, 5]
  )
); // [[1,5],[6,9]]

// Test Case 2
console.log(
  insert(
    [
      [1, 2],
      [3, 5],
      [6, 7],
      [8, 10],
      [12, 16],
    ],
    [4, 8]
  )
);
// [[1,2],[3,10],[12,16]]

// Test Case 3
console.log(insert([], [5, 7])); // [[5,7]]

Time Complexity: O(n)
Space Complexity: O(1)


Problem 33: Merge Intervals (Interval)

Difficulty: Medium
LeetCode: Link

Description

Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals.

JavaScript Solution

/**
 * @param {number[][]} intervals
 * @return {number[][]}
 */
function merge(intervals) {
  if (intervals.length <= 1) return intervals;

  intervals.sort((a, b) => a[0] - b[0]);

  const merged = [intervals[0]];

  for (let i = 1; i < intervals.length; i++) {
    const last = merged[merged.length - 1];
    const current = intervals[i];

    if (current[0] <= last[1]) {
      // Overlapping, merge them
      last[1] = Math.max(last[1], current[1]);
    } else {
      merged.push(current);
    }
  }

  return merged;
}

Test Cases

// Test Case 1
console.log(
  merge([
    [1, 3],
    [2, 6],
    [8, 10],
    [15, 18],
  ])
);
// [[1,6],[8,10],[15,18]]

// Test Case 2
console.log(
  merge([
    [1, 4],
    [4, 5],
  ])
); // [[1,5]]

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

Time Complexity: O(n log n)
Space Complexity: O(1)


Problem 34: Non-overlapping Intervals (Interval)

Difficulty: Medium
LeetCode: Link

Description

Given an array of intervals where intervals[i] = [starti, endi], return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.

JavaScript Solution

/**
 * @param {number[][]} intervals
 * @return {number}
 */
function eraseOverlapIntervals(intervals) {
  if (intervals.length <= 1) return 0;

  intervals.sort((a, b) => a[1] - b[1]);

  let count = 0;
  let prevEnd = intervals[0][1];

  for (let i = 1; i < intervals.length; i++) {
    const current = intervals[i];

    if (current[0] < prevEnd) {
      count++;
      prevEnd = Math.min(prevEnd, current[1]);
    } else {
      prevEnd = current[1];
    }
  }

  return count;
}

Test Cases

// Test Case 1
console.log(
  eraseOverlapIntervals([
    [1, 2],
    [2, 3],
    [3, 4],
    [1, 3],
  ])
); // 1

// Test Case 2
console.log(
  eraseOverlapIntervals([
    [1, 2],
    [1, 2],
    [1, 2],
  ])
); // 2

// Test Case 3
console.log(
  eraseOverlapIntervals([
    [1, 2],
    [2, 3],
  ])
); // 0

Time Complexity: O(n log n)
Space Complexity: O(1)


Linked List Problems (6/6)

Problem 35: Reverse Linked List (Linked List)

Difficulty: Easy
LeetCode: Link

Description

Given the head of a singly linked list, reverse the list, and return the reversed list.

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
function reverseList(head) {
  let prev = null;
  let current = head;

  while (current !== null) {
    const next = current.next;
    current.next = prev;
    prev = current;
    current = next;
  }

  return prev;
}

Test Cases

// Helper function to create linked list
function createList(arr) {
  let head = null;
  let current = null;
  for (const val of arr) {
    const node = { val, next: null };
    if (!head) {
      head = node;
      current = node;
    } else {
      current.next = node;
      current = node;
    }
  }
  return head;
}

// Helper function to convert list to array
function listToArray(head) {
  const result = [];
  let current = head;
  while (current) {
    result.push(current.val);
    current = current.next;
  }
  return result;
}

// Test Case 1
const list1 = createList([1, 2, 3, 4, 5]);
const reversed1 = reverseList(list1);
console.log(listToArray(reversed1)); // [5, 4, 3, 2, 1]

// Test Case 2
const list2 = createList([1, 2]);
const reversed2 = reverseList(list2);
console.log(listToArray(reversed2)); // [2, 1]

// Test Case 3
console.log(listToArray(reverseList(null))); // []

Time Complexity: O(n)
Space Complexity: O(1)


Problem 36: Linked List Cycle (Linked List)

Difficulty: Easy
LeetCode: Link

Description

Given the head, determine if a linked list has a cycle in it.

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
function hasCycle(head) {
  let slow = head;
  let fast = head;

  while (fast !== null && fast.next !== null) {
    slow = slow.next;
    fast = fast.next.next;

    if (slow === fast) {
      return true;
    }
  }

  return false;
}

Test Cases

// Test Case 1 - No cycle
const noCycleList = createList([1, 2, 3, 4]);
console.log(hasCycle(noCycleList)); // false

// Test Case 2 - With cycle
const cycleList = createList([1, 2, 3]);
// Create a cycle: 1 -> 2 -> 3 -> 2
let current = cycleList;
while (current.next) current = current.next;
current.next = cycleList.next;
console.log(hasCycle(cycleList)); // true

// Test Case 3 - Single node
console.log(hasCycle({ val: 1, next: null })); // false

Time Complexity: O(n)
Space Complexity: O(1)


Problem 37: Merge Two Sorted Lists (Linked List)

Difficulty: Easy
LeetCode: Link

Description

Merge two sorted linked lists and return it as a sorted list.

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
function mergeTwoLists(list1, list2) {
  const dummy = new ListNode();
  let current = dummy;

  while (list1 !== null && list2 !== null) {
    if (list1.val <= list2.val) {
      current.next = list1;
      list1 = list1.next;
    } else {
      current.next = list2;
      list2 = list2.next;
    }
    current = current.next;
  }

  current.next = list1 !== null ? list1 : list2;

  return dummy.next;
}

Test Cases

// Test Case 1
const listA = createList([1, 2, 4]);
const listB = createList([1, 3, 4]);
console.log(listToArray(mergeTwoLists(listA, listB))); // [1, 1, 2, 3, 4, 4]

// Test Case 2
const listC = createList([]);
const listD = createList([0]);
console.log(listToArray(mergeTwoLists(listC, listD))); // [0]

// Test Case 3
console.log(listToArray(mergeTwoLists(null, null))); // []

Time Complexity: O(m + n)
Space Complexity: O(1)


Problem 38: Merge K Sorted Lists (Linked List)

Difficulty: Hard
LeetCode: Link

Description

Given an array of linked lists lists, each linked list is sorted in ascending order. Merge all the linked lists into one sorted linked list.

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
function mergeKLists(lists) {
  if (lists.length === 0) return null;

  const mergeTwo = (l1, l2) => {
    const dummy = new ListNode();
    let current = dummy;

    while (l1 && l2) {
      if (l1.val < l2.val) {
        current.next = l1;
        l1 = l1.next;
      } else {
        current.next = l2;
        l2 = l2.next;
      }
      current = current.next;
    }

    current.next = l1 || l2;
    return dummy.next;
  };

  while (lists.length > 1) {
    const mergedLists = [];
    for (let i = 0; i < lists.length; i += 2) {
      const l1 = lists[i];
      const l2 = i + 1 < lists.length ? lists[i + 1] : null;
      mergedLists.push(mergeTwo(l1, l2));
    }
    lists = mergedLists;
  }

  return lists[0];
}

Test Cases

// Test Case 1
const lists1 = [
  createList([1, 4, 5]),
  createList([1, 3, 4]),
  createList([2, 6]),
];
console.log(listToArray(mergeKLists(lists1))); // [1, 1, 2, 3, 4, 4, 5, 6]

// Test Case 2
console.log(listToArray(mergeKLists([]))); // []

// Test Case 3
console.log(listToArray(mergeKLists([createList([])]))); // []

Time Complexity: O(N log k) where N is total nodes, k is number of lists
Space Complexity: O(1)


Problem 39: Remove Nth Node From End of List (Linked List)

Difficulty: Medium
LeetCode: Link

Description

Given the head of a linked list, remove the nth node from the end of the list and return its head.

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
function removeNthFromEnd(head, n) {
  const dummy = new ListNode(0, head);
  let fast = dummy;
  let slow = dummy;

  // Move fast n steps ahead
  for (let i = 0; i <= n; i++) {
    fast = fast.next;
  }

  // Move both until fast reaches end
  while (fast !== null) {
    slow = slow.next;
    fast = fast.next;
  }

  // Remove nth node
  slow.next = slow.next.next;

  return dummy.next;
}

Test Cases

// Test Case 1
const list1 = createList([1, 2, 3, 4, 5]);
console.log(listToArray(removeNthFromEnd(list1, 2))); // [1, 2, 3, 5]

// Test Case 2
const list2 = createList([1]);
console.log(listToArray(removeNthFromEnd(list2, 1))); // []

// Test Case 3
const list3 = createList([1, 2]);
console.log(listToArray(removeNthFromEnd(list3, 1))); // [1]

Time Complexity: O(n)
Space Complexity: O(1)


Problem 40: Reorder List (Linked List)

Difficulty: Medium
LeetCode: Link

Description

Given a singly linked list L: L0 → L1 → … → Ln-1 → Ln, reorder it to: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

JavaScript Solution

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {void} Do not return anything, modify head in-place instead.
 */
function reorderList(head) {
  if (!head || !head.next) return;

  // Step 1: Find middle of the list
  let slow = head;
  let fast = head;
  while (fast.next && fast.next.next) {
    slow = slow.next;
    fast = fast.next.next;
  }

  // Step 2: Reverse second half
  let second = slow.next;
  slow.next = null; // Split the list

  let prev = null;
  while (second) {
    const next = second.next;
    second.next = prev;
    prev = second;
    second = next;
  }

  // Step 3: Merge two halves
  let first = head;
  second = prev;

  while (second) {
    const temp1 = first.next;
    const temp2 = second.next;

    first.next = second;
    second.next = temp1;

    first = temp1;
    second = temp2;
  }
}

Test Cases

// Test Case 1
const list1 = createList([1, 2, 3, 4]);
reorderList(list1);
console.log(listToArray(list1)); // [1, 4, 2, 3]

// Test Case 2
const list2 = createList([1, 2, 3, 4, 5]);
reorderList(list2);
console.log(listToArray(list2)); // [1, 5, 2, 4, 3]

// Test Case 3
const list3 = createList([1]);
reorderList(list3);
console.log(listToArray(list3)); // [1]

Time Complexity: O(n)
Space Complexity: O(1)


Matrix Problems (4/4)

Problem 41: Set Matrix Zeroes (Matrix)

Difficulty: Medium
LeetCode: Link

Description

Given an m x n integer matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

JavaScript Solution

/**
 * @param {number[][]} matrix
 * @return {void} Do not return anything, modify matrix in-place instead.
 */
function setZeroes(matrix) {
  const rows = matrix.length;
  const cols = matrix[0].length;
  let firstRowZero = false;
  let firstColZero = false;

  // Check if first row has any zeros
  for (let j = 0; j < cols; j++) {
    if (matrix[0][j] === 0) {
      firstRowZero = true;
      break;
    }
  }

  // Check if first column has any zeros
  for (let i = 0; i < rows; i++) {
    if (matrix[i][0] === 0) {
      firstColZero = true;
      break;
    }
  }

  // Use first row and column as markers
  for (let i = 1; i < rows; i++) {
    for (let j = 1; j < cols; j++) {
      if (matrix[i][j] === 0) {
        matrix[i][0] = 0;
        matrix[0][j] = 0;
      }
    }
  }

  // Zero out cells based on markers
  for (let i = 1; i < rows; i++) {
    for (let j = 1; j < cols; j++) {
      if (matrix[i][0] === 0 || matrix[0][j] === 0) {
        matrix[i][j] = 0;
      }
    }
  }

  // Zero out first row if needed
  if (firstRowZero) {
    for (let j = 0; j < cols; j++) {
      matrix[0][j] = 0;
    }
  }

  // Zero out first column if needed
  if (firstColZero) {
    for (let i = 0; i < rows; i++) {
      matrix[i][0] = 0;
    }
  }
}

Test Cases

// Test Case 1
const matrix1 = [
  [1, 1, 1],
  [1, 0, 1],
  [1, 1, 1],
];
setZeroes(matrix1);
console.log(matrix1); // [[1,0,1],[0,0,0],[1,0,1]]

// Test Case 2
const matrix2 = [
  [0, 1, 2, 0],
  [3, 4, 5, 2],
  [1, 3, 1, 5],
];
setZeroes(matrix2);
console.log(matrix2); // [[0,0,0,0],[0,4,5,0],[0,3,1,0]]

// Test Case 3
const matrix3 = [[1]];
setZeroes(matrix3);
console.log(matrix3); // [[1]]

Time Complexity: O(m × n)
Space Complexity: O(1)


Problem 42: Spiral Matrix (Matrix)

Difficulty: Medium
LeetCode: Link

Description

Given an m x n matrix, return all elements of the matrix in spiral order.

JavaScript Solution

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
function spiralOrder(matrix) {
  if (matrix.length === 0 || matrix[0].length === 0) return [];

  const result = [];
  let top = 0;
  let bottom = matrix.length - 1;
  let left = 0;
  let right = matrix[0].length - 1;

  while (top <= bottom && left <= right) {
    // Traverse from left to right
    for (let i = left; i <= right; i++) {
      result.push(matrix[top][i]);
    }
    top++;

    // Traverse from top to bottom
    for (let i = top; i <= bottom; i++) {
      result.push(matrix[i][right]);
    }
    right--;

    if (top <= bottom) {
      // Traverse from right to left
      for (let i = right; i >= left; i--) {
        result.push(matrix[bottom][i]);
      }
      bottom--;
    }

    if (left <= right) {
      // Traverse from bottom to top
      for (let i = bottom; i >= top; i--) {
        result.push(matrix[i][left]);
      }
      left++;
    }
  }

  return result;
}

Test Cases

// Test Case 1
console.log(
  spiralOrder([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
  ])
);
// [1,2,3,6,9,8,7,4,5]

// Test Case 2
console.log(
  spiralOrder([
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
  ])
);
// [1,2,3,4,8,12,11,10,9,5,6,7]

// Test Case 3
console.log(spiralOrder([[1]])); // [1]

Time Complexity: O(m × n)
Space Complexity: O(1)


Problem 43: Rotate Image (Matrix)

Difficulty: Medium
LeetCode: Link

Description

Given an n x n 2D matrix representing an image, rotate the image by 90 degrees clockwise in-place.

JavaScript Solution

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

  // Transpose the matrix
  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
    }
  }

  // Reverse each row
  for (let i = 0; i < n; i++) {
    matrix[i].reverse();
  }
}

Test Cases

// Test Case 1
const matrix1 = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];
rotate(matrix1);
console.log(matrix1); // [[7,4,1],[8,5,2],[9,6,3]]

// Test Case 2
const matrix2 = [
  [5, 1, 9, 11],
  [2, 4, 8, 10],
  [13, 3, 6, 7],
  [15, 14, 12, 16],
];
rotate(matrix2);
console.log(matrix2); // [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

// Test Case 3
const matrix3 = [[1]];
rotate(matrix3);
console.log(matrix3); // [[1]]

Time Complexity: O(n^2)
Space Complexity: O(1)


Problem 44: Word Search (Matrix)

Difficulty: Medium
LeetCode: Link

Description

Given an m x n grid and a word, return true if the word exists in the grid.

JavaScript Solution

/**
 * @param {character[][]} board
 * @param {string} word
 * @return {boolean}
 */
function exist(board, word) {
  const rows = board.length;
  const cols = board[0].length;

  const dfs = (row, col, index) => {
    if (index === word.length) return true;

    if (
      row < 0 ||
      row >= rows ||
      col < 0 ||
      col >= cols ||
      board[row][col] !== word[index]
    ) {
      return false;
    }

    // Mark the cell as visited
    const temp = board[row][col];
    board[row][col] = "#";

    // Check all four directions
    const found =
      dfs(row + 1, col, index + 1) ||
      dfs(row - 1, col, index + 1) ||
      dfs(row, col + 1, index + 1) ||
      dfs(row, col - 1, index + 1);

    // Restore the cell
    board[row][col] = temp;

    return found;
  };

  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      if (board[i][j] === word[0] && dfs(i, j, 0)) {
        return true;
      }
    }
  }

  return false;
}

Test Cases

// Test Case 1
const board1 = [
  ["A", "B", "C", "E"],
  ["S", "F", "C", "S"],
  ["A", "D", "E", "E"],
];
console.log(exist(board1, "ABCCED")); // true

// Test Case 2
console.log(exist(board1, "SEE")); // true

// Test Case 3
console.log(exist(board1, "ABCB")); // false

// Test Case 4
const board2 = [["a"]];
console.log(exist(board2, "a")); // true

Time Complexity: O(m × n × 4^L) where L is word length
Space Complexity: O(L) due to recursion


String Problems (10/10)

Problem 45: Longest Substring Without Repeating Characters (String)

Difficulty: Medium
LeetCode: Link

Description

Given a string s, return the length of the longest substring without repeating characters.

JavaScript Solution

/**
 * @param {string} s
 * @return {number}
 */
function lengthOfLongestSubstring(s) {
  const charMap = new Map();
  let maxLen = 0;
  let left = 0;

  for (let right = 0; right < s.length; right++) {
    const char = s[right];

    if (charMap.has(char) && charMap.get(char) >= left) {
      left = charMap.get(char) + 1;
    }

    charMap.set(char, right);
    maxLen = Math.max(maxLen, right - left + 1);
  }

  return maxLen;
}

Test Cases

// Test Case 1
console.log(lengthOfLongestSubstring("abcabcbb")); // 3

// Test Case 2
console.log(lengthOfLongestSubstring("bbbbb")); // 1

// Test Case 3
console.log(lengthOfLongestSubstring("pwwkew")); // 3

Time Complexity: O(n)
Space Complexity: O(min(n, charset size))


Problem 46: Longest Repeating Character Replacement (String)

Difficulty: Medium
LeetCode: Link

Description

You are given a string s and an integer k. Find the length of the longest substring containing the same letter after replacing at most k characters.

JavaScript Solution

/**
 * @param {string} s
 * @param {number} k
 * @return {number}
 */
function characterReplacement(s, k) {
  const count = new Array(26).fill(0);
  let maxLen = 0;
  let maxCount = 0;
  let left = 0;

  for (let right = 0; right < s.length; right++) {
    const idx = s.charCodeAt(right) - "A".charCodeAt(0);
    count[idx]++;
    maxCount = Math.max(maxCount, count[idx]);

    while (right - left + 1 - maxCount > k) {
      const leftIdx = s.charCodeAt(left) - "A".charCodeAt(0);
      count[leftIdx]--;
      left++;
    }

    maxLen = Math.max(maxLen, right - left + 1);
  }

  return maxLen;
}

Test Cases

// Test Case 1
console.log(characterReplacement("ABAB", 2)); // 4

// Test Case 2
console.log(characterReplacement("AABABBA", 1)); // 4

// Test Case 3
console.log(characterReplacement("AAAA", 2)); // 4

Time Complexity: O(n)
Space Complexity: O(1)


Problem 47: Minimum Window Substring (String)

Difficulty: Hard
LeetCode: Link

Description

Given two strings s and t, return the minimum window substring of s which will contain all the characters in t.

JavaScript Solution

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
function minWindow(s, t) {
  if (s.length === 0 || t.length === 0) return "";

  const need = new Map();
  for (const char of t) {
    need.set(char, (need.get(char) || 0) + 1);
  }

  let left = 0;
  let right = 0;
  let formed = 0;
  let required = need.size;
  let result = [-Infinity, 0, 0]; // [length, left, right]

  const windowCounts = new Map();

  while (right < s.length) {
    const char = s[right];
    windowCounts.set(char, (windowCounts.get(char) || 0) + 1);

    if (need.has(char) && windowCounts.get(char) === need.get(char)) {
      formed++;
    }

    while (left <= right && formed === required) {
      if (right - left + 1 < result[0]) {
        result[0] = right - left + 1;
        result[1] = left;
        result[2] = right;
      }

      const leftChar = s[left];
      windowCounts.set(leftChar, windowCounts.get(leftChar) - 1);

      if (
        need.has(leftChar) &&
        windowCounts.get(leftChar) < need.get(leftChar)
      ) {
        formed--;
      }

      left++;
    }

    right++;
  }

  return result[0] === -Infinity ? "" : s.substring(result[1], result[2] + 1);
}

Test Cases

// Test Case 1
console.log(minWindow("ADOBECODEBANC", "ABC")); // "BANC"

// Test Case 2
console.log(minWindow("a", "a")); // "a"

// Test Case 3
console.log(minWindow("a", "aa")); // ""

Time Complexity: O(|s| + |t|)
Space Complexity: O(|s| + |t|)


Problem 48: Valid Anagram (String)

Difficulty: Easy
LeetCode: Link

Description

Given two strings s and t, return true if t is an anagram of s, and false otherwise.

JavaScript Solution

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

  const count = new Array(26).fill(0);

  for (let i = 0; i < s.length; i++) {
    count[s.charCodeAt(i) - "a".charCodeAt(0)]++;
    count[t.charCodeAt(i) - "a".charCodeAt(0)]--;
  }

  for (const c of count) {
    if (c !== 0) return false;
  }

  return true;
}

Test Cases

// Test Case 1
console.log(isAnagram("anagram", "nagaram")); // true

// Test Case 2
console.log(isAnagram("rat", "car")); // false

// Test Case 3
console.log(isAnagram("", "")); // true

Time Complexity: O(n)
Space Complexity: O(1)


Problem 49: Group Anagrams (String)

Difficulty: Medium
LeetCode: Link

Description

Given an array of strings strs, group the anagrams together.

JavaScript Solution

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

  for (const str of strs) {
    const key = str.split("").sort().join("");
    if (!groups.has(key)) {
      groups.set(key, []);
    }
    groups.get(key).push(str);
  }

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

Test Cases

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

// Test Case 2
console.log(groupAnagrams([""])); // [[""]]

// Test Case 3
console.log(groupAnagrams(["a"])); // [["a"]]

Time Complexity: O(n × k log k) where n is number of strings, k is max string length
Space Complexity: O(n × k)


Problem 50: Valid Parentheses (String)

Difficulty: Easy
LeetCode: Link

Description

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

JavaScript Solution

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

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

  return stack.length === 0;
}

Test Cases

// Test Case 1
console.log(isValid("()")); // true

// Test Case 2
console.log(isValid("()[]{}")); // true

// Test Case 3
console.log(isValid("(]")); // false

Time Complexity: O(n)
Space Complexity: O(n)


Problem 51: Valid Palindrome (String)

Difficulty: Easy
LeetCode: Link

Description

Given a string s, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

JavaScript Solution

/**
 * @param {string} s
 * @return {boolean}
 */
function isPalindrome(s) {
  let left = 0;
  let right = s.length - 1;

  while (left < right) {
    while (left < right && !isAlphaNumeric(s[left])) {
      left++;
    }
    while (left < right && !isAlphaNumeric(s[right])) {
      right--;
    }

    if (s[left].toLowerCase() !== s[right].toLowerCase()) {
      return false;
    }

    left++;
    right--;
  }

  return true;
}

function isAlphaNumeric(char) {
  const code = char.charCodeAt(0);
  return (
    (code >= 48 && code <= 57) || // 0-9
    (code >= 65 && code <= 90) || // A-Z
    (code >= 97 && code <= 122)
  ); // a-z
}

Test Cases

// Test Case 1
console.log(isPalindrome("A man, a plan, a canal: Panama")); // true

// Test Case 2
console.log(isPalindrome("race a car")); // false

// Test Case 3
console.log(isPalindrome(" ")); // true

Time Complexity: O(n)
Space Complexity: O(1)


Problem 52: Longest Palindromic Substring (String)

Difficulty: Medium
LeetCode: Link

Description

Given a string s, return the longest palindromic substring in s.

JavaScript Solution

/**
 * @param {string} s
 * @return {string}
 */
function longestPalindrome(s) {
  let start = 0;
  let maxLen = 1;

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

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

    const currentLen = Math.max(len1, len2);
    if (currentLen > maxLen) {
      maxLen = currentLen;
      start = i - Math.floor((currentLen - 1) / 2);
    }
  }

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

Test Cases

// Test Case 1
console.log(longestPalindrome("babad")); // "bab" or "aba"

// Test Case 2
console.log(longestPalindrome("cbbd")); // "bb"

// Test Case 3
console.log(longestPalindrome("a")); // "a"

Time Complexity: O(n^2)
Space Complexity: O(1)


Problem 53: Palindromic Substrings (String)

Difficulty: Medium
LeetCode: Link

Description

Given a string s, return the count of palindromic substrings in it.

JavaScript Solution

/**
 * @param {string} s
 * @return {number}
 */
function countSubstrings(s) {
  let count = 0;

  const expandAroundCenter = (left, right) => {
    while (left >= 0 && right < s.length && s[left] === s[right]) {
      count++;
      left--;
      right++;
    }
  };

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

  return count;
}

Test Cases

// Test Case 1
console.log(countSubstrings("abc")); // 3

// Test Case 2
console.log(countSubstrings("aaa")); // 6

// Test Case 3
console.log(countSubstrings("")); // 0

Time Complexity: O(n^2)
Space Complexity: O(1)


Problem 54: Encode and Decode Strings (String) - Premium

Difficulty: Medium
LeetCode: Link

Description

Design an algorithm to encode a list of strings to a single string. The encoded string is then decoded back to the original list of strings.

JavaScript Solution

/**
 * Encodes a list of strings to a single string.
 *
 * @param {string[]} strs
 * @return {string}
 */
var encode = function (strs) {
  let encoded = "";
  for (const str of strs) {
    encoded += str.length + "#" + str;
  }
  return encoded;
};

/**
 * Decodes a single string to a list of strings.
 *
 * @param {string} s
 * @return {string[]}
 */
var decode = function (s) {
  const decoded = [];
  let i = 0;

  while (i < s.length) {
    let j = i;
    while (s[j] !== "#") {
      j++;
    }
    const len = parseInt(s.substring(i, j));
    const str = s.substring(j + 1, j + 1 + len);
    decoded.push(str);
    i = j + 1 + len;
  }

  return decoded;
};

Test Cases

// Test Case 1
const encoded1 = encode(["hello", "world"]);
console.log(decode(encoded1)); // ["hello","world"]

// Test Case 2
const encoded2 = encode([""]);
console.log(decode(encoded2)); // [""]

// Test Case 3
const encoded3 = encode(["a", "b", "c"]);
console.log(decode(encoded3)); // ["a","b","c"]

Time Complexity: O(n) for both encode and decode
Space Complexity: O(n)


Tree Problems (13/13)

Problem 55: Maximum Depth of Binary Tree (Tree)

Difficulty: Easy
LeetCode: Link

Description

Given the root of a binary tree, return its maximum depth.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
function maxDepth(root) {
  if (!root) return 0;

  return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}

Test Cases

// Helper function to create tree
function createTree(arr) {
  if (!arr.length) return null;
  const root = { val: arr[0], left: null, right: null };
  const queue = [root];
  let i = 1;

  while (queue.length && i < arr.length) {
    const node = queue.shift();
    if (i < arr.length && arr[i] !== null) {
      node.left = { val: arr[i], left: null, right: null };
      queue.push(node.left);
    }
    i++;
    if (i < arr.length && arr[i] !== null) {
      node.right = { val: arr[i], left: null, right: null };
      queue.push(node.right);
    }
    i++;
  }
  return root;
}

// Test Case 1
console.log(maxDepth(createTree([3, 9, 20, null, null, 15, 7]))); // 3

// Test Case 2
console.log(maxDepth(createTree([1, null, 2]))); // 2

// Test Case 3
console.log(maxDepth(null)); // 0

Time Complexity: O(n)
Space Complexity: O(h) where h is tree height


Problem 56: Same Tree (Tree)

Difficulty: Easy
LeetCode: Link

Description

Given the roots of two binary trees p and q, check if they are the same tree.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
function isSameTree(p, q) {
  if (!p && !q) return true;
  if (!p || !q) return false;
  if (p.val !== q.val) return false;

  return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}

Test Cases

// Test Case 1
console.log(isSameTree(createTree([1, 2, 3]), createTree([1, 2, 3]))); // true

// Test Case 2
console.log(isSameTree(createTree([1, 2]), createTree([1, null, 2]))); // false

// Test Case 3
console.log(isSameTree(createTree([1, 2, 1]), createTree([1, 1, 2]))); // false

Time Complexity: O(n)
Space Complexity: O(h)


Problem 57: Invert Binary Tree (Tree)

Difficulty: Easy
LeetCode: Link

Description

Given the root of a binary tree, invert the tree, and return its root.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
function invertTree(root) {
  if (!root) return null;

  const left = invertTree(root.left);
  const right = invertTree(root.right);

  root.left = right;
  root.right = left;

  return root;
}

Test Cases

// Test Case 1
const tree1 = createTree([4, 2, 7, 1, 3, 6, 9]);
invertTree(tree1);
console.log(tree1); // Inverted tree structure

// Test Case 2
const tree2 = createTree([2, 1, 3]);
invertTree(tree2);
console.log(tree2); // Inverted tree structure

// Test Case 3
console.log(invertTree(null)); // null

Time Complexity: O(n)
Space Complexity: O(h)


Problem 58: Binary Tree Maximum Path Sum (Tree)

Difficulty: Hard
LeetCode: Link

Description

A path in a binary tree is a sequence of nodes where each adjacent pair of nodes are connected by an edge. Find the maximum path sum.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
function maxPathSum(root) {
  let maxSum = -Infinity;

  const dfs = node => {
    if (!node) return 0;

    const left = Math.max(0, dfs(node.left));
    const right = Math.max(0, dfs(node.right));

    maxSum = Math.max(maxSum, node.val + left + right);

    return node.val + Math.max(left, right);
  };

  dfs(root);
  return maxSum;
}

Test Cases

// Test Case 1
console.log(maxPathSum(createTree([1, 2, 3]))); // 6

// Test Case 2
console.log(maxPathSum(createTree([-10, 9, 20, null, null, 15, 7]))); // 42

// Test Case 3
console.log(maxPathSum(createTree([2, -1]))); // 2

Time Complexity: O(n)
Space Complexity: O(h)


Problem 59: Binary Tree Level Order Traversal (Tree)

Difficulty: Medium
LeetCode: Link

Description

Given the root of a binary tree, return the level order traversal of its nodes’ values.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
function levelOrder(root) {
  if (!root) return [];

  const result = [];
  const queue = [root];

  while (queue.length > 0) {
    const levelSize = queue.length;
    const currentLevel = [];

    for (let i = 0; i < levelSize; i++) {
      const node = queue.shift();
      currentLevel.push(node.val);

      if (node.left) queue.push(node.left);
      if (node.right) queue.push(node.right);
    }

    result.push(currentLevel);
  }

  return result;
}

Test Cases

// Test Case 1
console.log(levelOrder(createTree([3, 9, 20, null, null, 15, 7])));
// [[3],[9,20],[15,7]]

// Test Case 2
console.log(levelOrder(createTree([1]))); // [[1]]

// Test Case 3
console.log(levelOrder(null)); // []

Time Complexity: O(n)
Space Complexity: O(n)


Problem 60: Serialize and Deserialize Binary Tree (Tree)

Difficulty: Hard
LeetCode: Link

Description

Design an algorithm to serialize and deserialize a binary tree.

JavaScript Solution

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

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

  const dfs = node => {
    if (!node) {
      result.push("null");
      return;
    }
    result.push(node.val.toString());
    dfs(node.left);
    dfs(node.right);
  };

  dfs(root);
  return result.join(",");
};

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

  const 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

// Test Case 1
const tree1 = createTree([1, 2, 3, null, null, 4, 5]);
const serialized1 = serialize(tree1);
const deserialized1 = deserialize(serialized1);
console.log(levelOrder(deserialized1)); // [[1],[2,3],[4,5]]

// Test Case 2
const tree2 = createTree([]);
const serialized2 = serialize(tree2);
const deserialized2 = deserialize(serialized2);
console.log(deserialized2); // null

Time Complexity: O(n) for both serialize and deserialize
Space Complexity: O(n)


Problem 61: Subtree of Another Tree (Tree)

Difficulty: Easy
LeetCode: Link

Description

Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} subRoot
 * @return {boolean}
 */
function isSubtree(root, subRoot) {
  if (!subRoot) return true;
  if (!root) return false;

  if (isSameTree(root, subRoot)) {
    return true;
  }

  return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}

function isSameTree(p, q) {
  if (!p && !q) return true;
  if (!p || !q) return false;
  if (p.val !== q.val) return false;

  return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}

Test Cases

// Test Case 1
console.log(isSubtree(createTree([3, 4, 5, 1, 2]), createTree([4, 1, 2]))); // true

// Test Case 2
console.log(
  isSubtree(
    createTree([3, 4, 5, 1, 2, null, null, null, null, 0]),
    createTree([4, 1, 2])
  )
); // false

// Test Case 3
console.log(isSubtree(createTree([1, 1]), createTree([1]))); // true

Time Complexity: O(m × n) where m is nodes in root, n is nodes in subRoot
Space Complexity: O(h)


Problem 62: Construct Binary Tree from Preorder and Inorder Traversal (Tree)

Difficulty: Medium
LeetCode: Link

Description

Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal, return the binary tree.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {number[]} preorder
 * @param {number[]} inorder
 * @return {TreeNode}
 */
function buildTree(preorder, inorder) {
  const inorderMap = new Map();
  for (let i = 0; i < inorder.length; i++) {
    inorderMap.set(inorder[i], i);
  }

  let preorderIndex = 0;

  const arrayToTree = (left, right) => {
    if (left > right) return null;

    const rootValue = preorder[preorderIndex++];
    const root = new TreeNode(rootValue);

    root.left = arrayToTree(left, inorderMap.get(rootValue) - 1);
    root.right = arrayToTree(inorderMap.get(rootValue) + 1, right);

    return root;
  };

  return arrayToTree(0, inorder.length - 1);
}

Test Cases

// Test Case 1
const tree1 = buildTree([3, 9, 20, 15, 7], [9, 3, 15, 20, 7]);
console.log(levelOrder(tree1)); // [[3],[9,20],[15,7]]

// Test Case 2
const tree2 = buildTree([-1], [-1]);
console.log(levelOrder(tree2)); // [[-1]]

// Test Case 3
console.log(buildTree([], [])); // null

Time Complexity: O(n)
Space Complexity: O(n)


Problem 63: Validate Binary Search Tree (Tree)

Difficulty: Medium
LeetCode: Link

Description

Given the root of a binary tree, determine if it is a valid binary search tree (BST).

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
function isValidBST(root) {
  const validate = (node, min, max) => {
    if (!node) return true;

    if (
      (min !== null && node.val <= min) ||
      (max !== null && node.val >= max)
    ) {
      return false;
    }

    return (
      validate(node.left, min, node.val) && validate(node.right, node.val, max)
    );
  };

  return validate(root, null, null);
}

Test Cases

// Test Case 1
console.log(isValidBST(createTree([2, 1, 3]))); // true

// Test Case 2
console.log(isValidBST(createTree([5, 1, 4, null, null, 3, 6]))); // false

// Test Case 3
console.log(isValidBST(createTree([1, 1]))); // false

Time Complexity: O(n)
Space Complexity: O(h)


Problem 64: Kth Smallest Element in a BST (Tree)

Difficulty: Medium
LeetCode: Link

Description

Given the root of a BST, and an integer k, return the kth smallest element in the tree.

JavaScript Solution

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @param {number} k
 * @return {number}
 */
function kthSmallest(root, k) {
  let count = 0;
  let result = null;

  const inorder = node => {
    if (!node || result !== null) return;

    inorder(node.left);
    count++;
    if (count === k) {
      result = node.val;
      return;
    }
    inorder(node.right);
  };

  inorder(root);
  return result;
}

Test Cases

// Test Case 1
console.log(kthSmallest(createTree([3, 1, 4, null, 2]), 1)); // 1

// Test Case 2
console.log(kthSmallest(createTree([5, 3, 6, 2, 4, null, null, 1]), 3)); // 3

// Test Case 3
console.log(kthSmallest(createTree([1]), 1)); // 1

Time Complexity: O(n)
Space Complexity: O(h)


Problem 65: Lowest Common Ancestor of a Binary Search Tree (Tree)

Difficulty: Easy
LeetCode: Link

Description

Given a BST, find the lowest common ancestor (LCA) of two given nodes in the BST.

JavaScript Solution

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {TreeNode}
 */
function lowestCommonAncestor(root, p, q) {
  while (root) {
    if (p.val < root.val && q.val < root.val) {
      root = root.left;
    } else if (p.val > root.val && q.val > root.val) {
      root = root.right;
    } else {
      return root;
    }
  }
  return null;
}

Test Cases

// Test Case 1
const tree1 = createTree([6, 2, 8, 0, 4, 7, 9, null, null, 3, 5]);
const p1 = { val: 2 };
const q1 = { val: 8 };
console.log(lowestCommonAncestor(tree1, p1, q1).val); // 6

// Test Case 2
const p2 = { val: 2 };
const q2 = { val: 4 };
console.log(lowestCommonAncestor(tree1, p2, q2).val); // 2

// Test Case 3
const tree2 = createTree([2, 1]);
console.log(lowestCommonAncestor(tree2, { val: 2 }, { val: 1 }).val); // 2

Time Complexity: O(n)
Space Complexity: O(1)


Problem 66: Implement Trie (Prefix Tree) (Tree)

Difficulty: Medium
LeetCode: Link

Description

Implement a trie (prefix tree) with insert, search, and startsWith methods.

JavaScript Solution

class TrieNode {
  constructor() {
    this.children = {};
    this.isEndOfWord = false;
  }
}

class Trie {
  constructor() {
    this.root = new TrieNode();
  }

  /**
   * @param {string} word
   * @return {void}
   */
  insert(word) {
    let current = this.root;
    for (const char of word) {
      if (!current.children[char]) {
        current.children[char] = new TrieNode();
      }
      current = current.children[char];
    }
    current.isEndOfWord = true;
  }

  /**
   * @param {string} word
   * @return {boolean}
   */
  search(word) {
    let current = this.root;
    for (const char of word) {
      if (!current.children[char]) {
        return false;
      }
      current = current.children[char];
    }
    return current.isEndOfWord;
  }

  /**
   * @param {string} prefix
   * @return {boolean}
   */
  startsWith(prefix) {
    let current = this.root;
    for (const char of prefix) {
      if (!current.children[char]) {
        return false;
      }
      current = current.children[char];
    }
    return true;
  }
}

Test Cases

// Test Case 1
const trie1 = new Trie();
trie1.insert("apple");
console.log(trie1.search("apple")); // true
console.log(trie1.search("app")); // false
console.log(trie1.startsWith("app")); // true
trie1.insert("app");
console.log(trie1.search("app")); // true

// Test Case 2
const trie2 = new Trie();
trie2.insert("hello");
console.log(trie2.search("hell")); // false
console.log(trie2.startsWith("hell")); // true

// Test Case 3
const trie3 = new Trie();
console.log(trie3.search("a")); // false

Time Complexity: O(L) where L is word length for all operations
Space Complexity: O(N × L) where N is number of words, L is average word length


Heap Problems (2/2)

Problem 67: Top K Frequent Elements (Heap)

Difficulty: Medium
LeetCode: Link

Description

Given an integer array nums and an integer k, return the k most frequent elements.

JavaScript Solution

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
function topKFrequent(nums, k) {
  const frequency = new Map();

  for (const num of nums) {
    frequency.set(num, (frequency.get(num) || 0) + 1);
  }

  const buckets = new Array(nums.length + 1);
  for (let i = 0; i < buckets.length; i++) {
    buckets[i] = [];
  }

  for (const [num, freq] of frequency) {
    buckets[freq].push(num);
  }

  const result = [];
  for (let i = buckets.length - 1; i >= 0 && result.length < k; i--) {
    for (const num of buckets[i]) {
      result.push(num);
      if (result.length === k) break;
    }
  }

  return result;
}

Test Cases

// Test Case 1
console.log(topKFrequent([1, 1, 1, 2, 2, 3], 2)); // [1,2]

// Test Case 2
console.log(topKFrequent([1], 1)); // [1]

// Test Case 3
console.log(topKFrequent([4, 1, 2, 2, 3, 4, 4, 4, 4], 2)); // [4,2]

Time Complexity: O(n)
Space Complexity: O(n)


Problem 68: Find Median from Data Stream (Heap)

Difficulty: Hard
LeetCode: Link

Description

Implement a data structure that supports adding numbers and finding the median.

JavaScript Solution

class MedianFinder {
  constructor() {
    this.maxHeap = []; // Left half (smaller numbers)
    this.minHeap = []; // Right half (larger numbers)
  }

  /**
   * @param {number} num
   * @return {void}
   */
  addNum(num) {
    // Add to maxHeap first
    this.maxHeap.push(num);
    this.heapifyUp(this.maxHeap, true);

    // Move largest from maxHeap to minHeap
    const maxFromLeft = this.maxHeap.shift();
    this.heapifyDown(this.maxHeap, true);
    this.minHeap.push(maxFromLeft);
    this.heapifyUp(this.minHeap, false);

    // Balance heaps
    if (this.minHeap.length > this.maxHeap.length) {
      const minFromRight = this.minHeap.shift();
      this.heapifyDown(this.minHeap, false);
      this.maxHeap.push(minFromRight);
      this.heapifyUp(this.maxHeap, true);
    }
  }

  /**
   * @return {number}
   */
  findMedian() {
    if (this.maxHeap.length > this.minHeap.length) {
      return this.maxHeap[0];
    }
    return (this.maxHeap[0] + this.minHeap[0]) / 2;
  }

  heapifyUp(heap, isMaxHeap) {
    let index = heap.length - 1;
    while (index > 0) {
      const parentIndex = Math.floor((index - 1) / 2);
      if (
        (isMaxHeap && heap[parentIndex] >= heap[index]) ||
        (!isMaxHeap && heap[parentIndex] <= heap[index])
      ) {
        break;
      }
      [heap[parentIndex], heap[index]] = [heap[index], heap[parentIndex]];
      index = parentIndex;
    }
  }

  heapifyDown(heap, isMaxHeap) {
    let index = 0;
    while (true) {
      const leftChild = 2 * index + 1;
      const rightChild = 2 * index + 2;
      let swapIndex = index;

      if (leftChild < heap.length) {
        if (
          (isMaxHeap && heap[leftChild] > heap[swapIndex]) ||
          (!isMaxHeap && heap[leftChild] < heap[swapIndex])
        ) {
          swapIndex = leftChild;
        }
      }

      if (rightChild < heap.length) {
        if (
          (isMaxHeap && heap[rightChild] > heap[swapIndex]) ||
          (!isMaxHeap && heap[rightChild] < heap[swapIndex])
        ) {
          swapIndex = rightChild;
        }
      }

      if (swapIndex === index) break;

      [heap[index], heap[swapIndex]] = [heap[swapIndex], heap[index]];
      index = swapIndex;
    }
  }
}

Test Cases

// Test Case 1
const mf1 = new MedianFinder();
mf1.addNum(1);
mf1.addNum(2);
console.log(mf1.findMedian()); // 1.5
mf1.addNum(3);
console.log(mf1.findMedian()); // 2

// Test Case 2
const mf2 = new MedianFinder();
mf2.addNum(5);
console.log(mf2.findMedian()); // 5
mf2.addNum(15);
console.log(mf2.findMedian()); // 10

// Test Case 3
const mf3 = new MedianFinder();
mf3.addNum(-1);
mf3.addNum(-2);
mf3.addNum(-3);
console.log(mf3.findMedian()); // -2

Time Complexity: O(log n) for addNum, O(1) for findMedian
Space Complexity: O(n)


Study Timeline & Summary

Week 1: Arrays & Strings (20 problems)

Week 2: Binary & Dynamic Programming (16 problems)

Week 3: Graph & Interval (14 problems)

Week 4: Linked List & Matrix (10 problems)

Week 5: Tree & Heap (15 problems)

Key Learning Points

1. Pattern Recognition

2. Complexity Analysis

3. Problem-Solving Framework

  1. Understand the problem - Clarify requirements and constraints
  2. Brute force approach - Start with a simple solution
  3. Optimize - Look for patterns and apply appropriate algorithms
  4. Test thoroughly - Consider edge cases and validate solution

4. Common Interview Strategies

Final Tips

  1. Practice consistently - Daily practice builds muscle memory
  2. Review and revise - Revisit problems to reinforce learning
  3. Mock interviews - Practice explaining solutions verbally
  4. Focus on fundamentals - Strong basics help with variations
  5. Stay calm - Interview pressure affects performance

Progress Tracker

Use this checklist to track your progress:

[ ] Arrays (10/10)
[ ] Binary (5/5)
[ ] Dynamic Programming (11/11)
[ ] Graph (8/8)
[ ] Interval (6/6)
[ ] Linked List (6/6)
[ ] Matrix (4/4)
[ ] String (10/10)
[ ] Tree (13/13)
[ ] Heap (2/2)

Total: 75/75 problems completed

Congratulations! You now have a comprehensive collection of all Blind75 LeetCode problems with JavaScript solutions, test cases, and detailed explanations. Happy coding and good luck with your interviews! 🚀



Next Post
前端相关的各类知识汇总