Algorithms

On this page

An algorithm is a finite, well-defined sequence of steps that solves a problem. The right algorithm at scale can be the difference between milliseconds and hours.

Overview

Picking algorithms is mostly picking data structures first — the structure constrains what operations are cheap. After that, the cost model (memory access, cache behavior, I/O) often matters more than raw Big-O.

Complexity

  • O(1) — constant (hash lookup, array index).
  • O(log n) — binary search, balanced tree ops.
  • O(n) — linear scan.
  • O(n log n) — comparison-based sort, FFT.
  • O(n²) — naive pairwise (bubble sort).
  • O(2ⁿ), O(n!) — combinatorial; avoid for large n.
  • Space matters too — recursion depth, auxiliary arrays.

Sorting

  • Quicksort — O(n log n) avg, O(n²) worst; in place.
  • Mergesort — O(n log n) worst; stable; O(n) extra.
  • Heapsort — O(n log n); in place; not stable.
  • Insertion sort — O(n²) but excellent on near-sorted / small n.
  • Counting / radix — O(n + k); integer keys only.
  • Timsort — hybrid; default in Python & Java.

Searching

  • Linear search — O(n).
  • Binary search — O(log n) on sorted data.
  • Hashing — O(1) expected; collisions, load factor.
  • BFS / DFS for graphs and trees.
  • A* — heuristic-guided shortest path.

Graph Algorithms

  • Dijkstra — shortest path, non-negative weights, O((V+E) log V).
  • Bellman-Ford — handles negative edges, O(VE).
  • Floyd-Warshall — all-pairs, O(V³).
  • Kruskal / Prim — minimum spanning tree.
  • Topological sort — DAGs, scheduling.
  • Max flow — Edmonds-Karp, Dinic.

Design Paradigms

  • Divide & conquer — mergesort, FFT, Karatsuba.
  • Dynamic programming — overlapping subproblems + memoization.
  • Greedy — locally optimal choices (when they work).
  • Backtracking — DFS with pruning (SAT, N-queens).
  • Branch & bound — for optimization.
  • Randomized — Monte Carlo, Las Vegas.
reference page