Skip to main content

DSAPath18 mincore

Big-O Notation

Big-O notation describes how an algorithm's running time or space scales as input size grows. It is an upper bound on the growth rate, ignoring constants and lower-order terms. This page gives the formal definition, six worked examples, the relationship between Big-O / Big-Omega / Big-Theta, and the common mistakes that turn O-notation into a shibboleth instead of a tool.

DifficultyCore
TierTier 1
ModuleComplexity Foundations
LanguagesPython

Why This Matters

Big-O is the language algorithm engineers use to compare designs without running them. Two implementations of the same problem can differ by a constant factor on a benchmark and still differ by an order of magnitude on inputs the benchmark never reached. Big-O is the tool that catches that.

The notation is widely abused. Every interview asks for it; few candidates can state the formal definition. The mistakes compound: people quote O(nlogn)O(n \log n) for an algorithm that is in fact Θ(n2)\Theta(n^2) in the worst case, then act surprised when production traffic finds the worst case.

Formal Definition

A function f(n)f(n) is in O(g(n))O(g(n)) if there exist positive constants cc and n0n_0 such that for all nn0n \ge n_0,

0f(n)cg(n).0 \le f(n) \le c \cdot g(n).

In words: past some input size n0n_0, ff is at most a constant multiple of gg. The notation is an upper bound on growth rate, not an exact rate. An algorithm that runs in Θ(n)\Theta(n) time is also in O(n)O(n), in O(n2)O(n^2), and in O(2n)O(2^n) — Big-O does not promise tightness.

Worked Examples

Constant time, O(1)O(1). Accessing an array element by index. The cost does not depend on the array's length.

Logarithmic, O(logn)O(\log n). Binary search on a sorted array. Each comparison halves the search space, so the depth of the recursion is log2n\log_2 n.

Linear, O(n)O(n). Computing the sum of an array. One pass, one operation per element.

Linearithmic, O(nlogn)O(n \log n). Merge sort. The recursion tree has logn\log n levels and each level does nn work to merge.

Quadratic, O(n2)O(n^2). A naive nested loop comparing all pairs. The number of pairs is (n2)=n(n1)/2\binom{n}{2} = n(n-1)/2, which is Θ(n2)\Theta(n^2).

Exponential, O(2n)O(2^n). Enumerating all subsets of an nn-element set. The set has 2n2^n subsets, so any algorithm that materializes them all is at least Ω(2n)\Omega(2^n).

Big-O vs Big-Omega vs Big-Theta

Three related notations describe asymptotic growth at different bounds:

  • f(n)O(g(n))f(n) \in O(g(n)) means ff is at most a constant times gg asymptotically. Upper bound.
  • f(n)Ω(g(n))f(n) \in \Omega(g(n)) means ff is at least a constant times gg asymptotically. Lower bound.
  • f(n)Θ(g(n))f(n) \in \Theta(g(n)) means ff is both O(g)O(g) and Ω(g)\Omega(g). Exact rate up to constants.

Saying merge sort is "O(nlogn)O(n \log n)" is correct but loose. Saying merge sort is "Θ(nlogn)\Theta(n \log n)" is the tighter and more useful claim: it both upper- and lower-bounds the cost. Use Θ\Theta when you can prove it; use OO when you only have the upper bound.

Common Mistakes

Confusing average case with worst case. Quicksort with a random pivot is Θ(nlogn)\Theta(n \log n) in expectation. Its worst case is Θ(n2)\Theta(n^2). "Quicksort is O(nlogn)O(n \log n)" is true on average and false in the worst case. Both facts matter; know which you are quoting.

Dropping constants when they matter. Big-O hides constants by definition. For two algorithms in O(n)O(n), one with constant 3 and one with constant 30, the second is 10× slower at every input size. On a hot path, that constant decides whether your service meets its SLO. Big-O is for asymptotic comparison, not for picking between constant-factor variants.

Conflating time and space. Many algorithms have different time and space complexity. Hash-table lookup is O(1)O(1) time and O(n)O(n) space; merge sort is O(nlogn)O(n \log n) time and O(n)O(n) space. State which dimension you are bounding.

Ignoring the input distribution. "O(n2)O(n^2) in the worst case" is a statement about adversarial inputs. If your traffic is structured (sorted arrays, sparse graphs, low entropy), the worst case may never occur. The right answer depends on what you actually run, not what an adversary could pick.

References

  • Cormen, Leiserson, Rivest, Stein. Introduction to Algorithms (4th ed., 2022). Ch. 3 — Growth of Functions.
  • Knuth. The Art of Computer Programming, Volume 1: Fundamental Algorithms (3rd ed.). §1.2.11.

Next Topics