๐Ÿš€ From Brute Force to Optimal: Solving LeetCode Problems Step-by-Step (with JavaScript Examples)

When tackling coding problems, the smartest approach isnโ€™t always the fastestโ€”itโ€™s knowing how to evolve your solution over time. Whether you're a beginner or brushing up for interviews, this post will walk you through 8 techniques, each one solving an example problem in progressively smarter ways.


๐Ÿงฑ Step 1: Brute Force with Loops

๐Ÿ“Œ Problem: Two Sum

Given an array nums and a target value, return the indices of two numbers such that they add up to the target.

๐Ÿง  Brute Force Solution

function twoSum(nums, target) {
  for (let i = 0; i < nums.length; i++) {
    for (let j = i + 1; j < nums.length; j++) {
      if (nums[i] + nums[j] === target) {
        return [i, j];
      }
    }
  }
}

๐Ÿ” Analysis

  • โœ… Easy to understand

  • โŒ Time: O(nยฒ) โ†’ slow for large arrays


๐Ÿงฎ Step 2: Hash Map Optimization

๐Ÿ’ก Use hashing to store previously seen elements

function twoSum(nums, target) {
  const map = new Map();
  for (let i = 0; i < nums.length; i++) {
    const diff = target - nums[i];
    if (map.has(diff)) return [map.get(diff), i];
    map.set(nums[i], i);
  }
}

๐Ÿ” Analysis

  • โœ… Time reduced to O(n)

  • โœ… More scalable


๐Ÿ” Step 3: Sliding Window

๐Ÿ“Œ Problem: Longest Substring Without Repeating Characters

๐Ÿง  Brute Force (Nested Loops)

function lengthOfLongestSubstring(s) {
  let max = 0;
  for (let i = 0; i < s.length; i++) {
    let set = new Set();
    for (let j = i; j < s.length; j++) {
      if (set.has(s[j])) break;
      set.add(s[j]);
    }
    max = Math.max(max, set.size);
  }
  return max;
}

๐Ÿง  Optimized with Sliding Window

function lengthOfLongestSubstring(s) {
  let set = new Set();
  let left = 0, maxLen = 0;

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

๐Ÿ” Analysis

  • โŒ Brute force: O(nยฒ)

  • โœ… Sliding window: O(n)


๐Ÿ“ฆ Step 4: Prefix Sum

๐Ÿ“Œ Problem: Subarray Sum Equals K

๐Ÿง  Optimized with Prefix Sum + Map

function subarraySum(nums, k) {
  const map = new Map();
  map.set(0, 1);
  let count = 0, sum = 0;

  for (const num of nums) {
    sum += num;
    if (map.has(sum - k)) count += map.get(sum - k);
    map.set(sum, (map.get(sum) || 0) + 1);
  }
  return count;
}

๐Ÿ” Analysis

  • โœ… Handles multiple subarrays

  • โœ… Time: O(n)

  • โœ… Space: O(n)


๐Ÿ“Œ Problem: Find Insert Position

function searchInsert(nums, target) {
  let left = 0, 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 left;
}

๐Ÿ” Analysis

  • โœ… Efficient for sorted arrays

  • โœ… Time: O(log n)


๐Ÿงญ Step 6: Heap / Greedy

๐Ÿ“Œ Problem: Top K Frequent Elements

๐Ÿง  Using Map + Sort (Greedy-style)

function topKFrequent(nums, k) {
  const count = new Map();
  for (const num of nums) {
    count.set(num, (count.get(num) || 0) + 1);
  }
  const sorted = [...count.entries()].sort((a, b) => b[1] - a[1]);
  return sorted.slice(0, k).map(([num]) => num);
}

๐Ÿ” Analysis

  • โœ… Time: O(n log n)

  • ๐Ÿ› ๏ธ Can optimize with heap for O(n log k)


๐Ÿงต Step 7: Backtracking

๐Ÿ“Œ Problem: Subsets

๐Ÿง  Recursive Backtracking

function subsets(nums) {
  const res = [];
  function backtrack(start, path) {
    res.push([...path]);
    for (let i = start; i < nums.length; i++) {
      path.push(nums[i]);
      backtrack(i + 1, path);
      path.pop();
    }
  }
  backtrack(0, []);
  return res;
}

๐Ÿ” Analysis

  • โœ… Generates all combinations

  • โŒ Time: O(2โฟ)


๐Ÿ—๏ธ Step 8: Dynamic Programming

๐Ÿ“Œ Problem: Climbing Stairs

๐Ÿง  Bottom-Up DP

function climbStairs(n) {
  if (n <= 2) return n;
  let dp = [1, 1];
  for (let i = 2; i <= n; i++) {
    dp[i] = dp[i - 1] + dp[i - 2];
  }
  return dp[n];
}

๐Ÿ” Analysis

  • โœ… Time: O(n)

  • โœ… Space: O(n) (can optimize to O(1))


๐Ÿ”„ Final Recap Table

StepTechniqueExample ProblemTime Complexity
1Brute ForceTwo SumO(nยฒ)
2Hash Map / SetTwo Sum (Optimized)O(n)
3Sliding WindowLongest Substring Without RepeatO(n)
4Prefix SumSubarray Sum Equals KO(n)
5Binary SearchSearch Insert PositionO(log n)
6Greedy / Sort / HeapTop K Frequent ElementsO(n log k)
7BacktrackingSubsetsO(2โฟ)
8Dynamic ProgrammingClimbing StairsO(n)

๐Ÿง  Conclusion

When approaching a problem:

  1. Start with brute force to understand the core logic.

  2. Climb the ladderโ€”optimize with hash maps, two pointers, prefix sums, and beyond.

  3. Always analyze complexity and think: Can I do better?

Whether you're prepping for interviews or improving daily, this technique ladder gives you a structured way to level up. ๐Ÿš€

0
Subscribe to my newsletter

Read articles from Aakib Shah Sayed directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aakib Shah Sayed
Aakib Shah Sayed