Skip to main content

Algorithms Corner

Optional enrichment — practical algorithm concepts explained for beginners, without unnecessary abstraction.

Why Algorithms

You do not need to master algorithms to build web apps. But understanding the basics helps you:

  • Write code that performs well with real data sizes
  • Talk confidently in technical interviews
  • Recognize patterns in problems you have not seen before

This section stays practical and beginner-friendly. Every concept is shown with JavaScript examples.

Big O in Plain English

Big O notation describes how the time (or space) a piece of code needs grows as the input size grows. You do not need the math — just the intuition.

NotationPlain EnglishExample
O(1)Constant — same speed no matter how big the inputLooking up a value in an object by key
O(n)Linear — grows proportionally with inputLooping through an array once
O(n²)Quadratic — grows fast, gets slow for large inputsA loop inside a loop
O(log n)Logarithmic — fast, halves the problem each stepBinary search

Practical rule: For small inputs (dozens, hundreds), most code is fast enough. For large inputs (thousands, millions), nested loops get expensive fast.

Arrays vs Objects

Knowing when to use each one is one of the most practical algorithm skills.

Arrays are ordered lists. Use them when order matters or when you need to iterate over everything.

const names = ['Alice', 'Bob', 'Carol']
names[0]           // O(1) — fast
names.includes('Bob')  // O(n) — scans the whole array

Objects are key-value stores. Use them when you need fast lookup by a specific identifier.

const userById = {
  '001': { name: 'Alice' },
  '002': { name: 'Bob' },
}
userById['002']    // O(1) — instant lookup, regardless of size

The pattern: When you find yourself searching an array repeatedly for the same thing, convert it to an object or Map first.

Maps and Sets

Map is like an object but allows any type as a key and preserves insertion order.

const scores = new Map()
scores.set('Alice', 95)
scores.set('Bob', 87)
scores.get('Alice')   // 95
scores.has('Carol')   // false

Set stores unique values — duplicates are automatically ignored.

const tags = new Set(['js', 'react', 'js', 'css'])
// tags = set { 'js', 'react', 'css' }  — no duplicates

// deduplicate an array
const unique = [...new Set(someArray)]

Stacks and Queues

These are patterns for managing ordered collections of items.

Stack — last in, first out (LIFO). Like a stack of plates.

const stack = []
stack.push('first')
stack.push('second')
stack.pop()   // 'second' — removes the last item

Queue — first in, first out (FIFO). Like a line at a store.

const queue = []
queue.push('first')
queue.push('second')
queue.shift()  // 'first' — removes the first item

You use these patterns constantly without realizing it — browser history is a stack, task queues are queues.

Recursion Basics

A recursive function calls itself. Every recursive function needs a base case (when to stop) and a recursive case (the self-call that makes progress toward stopping).

function countdown(n) {
  if (n <= 0) {
    console.log('Done!')
    return
  }
  console.log(n)
  countdown(n - 1)   // calls itself with a smaller value
}

countdown(3)
// 3
// 2
// 1
// done!

A classic example — factorial:

function factorial(n) {
  if (n === 1) return 1          // base case
  return n * factorial(n - 1)   // recursive case
}

factorial(5)  // 120  (5 * 4 * 3 * 2 * 1)

Warning: Always make sure the base case will be reached, or the function will run forever and crash.

Sorting and Searching

JavaScript's built-in sort:

const nums = [3, 1, 4, 1, 5, 9, 2, 6]
nums.sort((a, b) => a - b)   // ascending: [1, 1, 2, 3, 4, 5, 6, 9]
nums.sort((a, b) => b - a)   // descending

Linear search — scan every element:

function findIndex(arr, target) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === target) return i
  }
  return -1
}
// o(n) — works on any array

Binary search — works only on sorted arrays, but much faster:

function binarySearch(arr, target) {
  let left = 0
  let right = arr.length - 1

  while (left <= right) {
    const mid = Math.floor((left + right) / 2)
    if (arr[mid] === target) return mid
    if (arr[mid] < target) left = mid + 1
    else right = mid - 1
  }
  return -1
}
// o(log n) — each step cuts the problem in half

Practice Resources

Once you are comfortable with the basics, these platforms offer good practice problems at beginner to intermediate level:

Start with what you know. Build confidence with easier problems before moving to harder ones.