Programming

Big O Notation Without the Math Panic

A practical, jargon-light explanation of Big O notation — what it actually measures, the complexities you'll encounter daily, and how to reason about them without a CS degree.

Ava ChenJuly 22, 20263 min read
Share:

Big O notation gets taught with more math notation than it needs. Here's the practical version.

What it actually measures

Big O describes how an algorithm's runtime (or memory) grows as the input size grows — not the actual speed in seconds. It answers one question: "if I double the input, roughly how much worse does this get?"

The complexities you'll actually see

NotationNameDoubling the input...Example
O(1)Constant...changes nothingArray index access
O(log n)Logarithmic...adds one stepBinary search
O(n)Linear...doubles the workA single loop through an array
O(n log n)Linearithmic...slightly more than doublesEfficient sorting (merge sort, quicksort)
O(n²)Quadratic...quadruples the workNested loops over the same data
O(2ⁿ)Exponential...squares the workNaive recursive Fibonacci

Spotting complexity in your own code

js
// O(n) — one pass
function sum(arr) {
  let total = 0;
  for (const n of arr) total += n;
  return total;
}
 
// O(n²) — nested loop over the same input
function hasDuplicate(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) return true;
    }
  }
  return false;
}

The second function re-scans the array for every element — that nested "loop inside a loop over the same data" pattern is the most common way O(n²) sneaks into real code.

The fix is usually a hash map

js
// O(n) — trade memory for speed
function hasDuplicate(arr) {
  const seen = new Set();
  for (const n of arr) {
    if (seen.has(n)) return true;
    seen.add(n);
  }
  return false;
}

Swapping an inner loop for a Set or Map lookup (O(1) average case) is the single most common optimization you'll make in practice — it turns O(n²) into O(n) at the cost of extra memory.

When it doesn't matter

For a list of 20 items, O(n²) vs O(n) is invisible to a user — both run in microseconds. Big O matters when n gets large or runs frequently (hot paths, data processing, anything operating on user-generated collections that can grow unbounded). Don't reach for cleverness on code that will only ever touch a handful of items — readability wins until the data proves otherwise.

Advertisement

Frequently Asked Questions

Ava Chen
Ava Chen

Senior Software Engineer

Ava writes about frontend architecture, React, and TypeScript. Previously built developer tools at scale-up startups.

Related Articles