Concept Discrete Mathematics βœ“ Live

Big-O Notation

Big-O notation describes how the running time or memory usage of an algorithm grows as its input size increases, focusing on the dominant long-run trend while deliberately ignoring implementation details, constant factors, and small-scale behaviour. Originally developed in pure number theory, it became the standard language computer scientists use to compare and reason rigorously about algorithm efficiency.

How slow does an algorithm get as the problem grows?

Imagine two methods for finding a specific name in a phone book. Method 1: start at page 1, and check every single name in order until you find it. Method 2: open to the middle, see if your target comes before or after, and repeat this halving process. For a phone book with a million names, Method 1 might require checking up to a million names in the worst case, while Method 2 needs at most about 20 checks (since 2²⁰ is already over a million). Big-O notation is how computer scientists precisely describe and compare this dramatic difference.

πŸ•ΈοΈ The two methods, in Big-O terms: Method 1 (checking everything) is O(n) β€” "linear time," roughly proportional to the input size n. Method 2 (repeated halving, called binary search) is O(log n) β€” "logarithmic time," growing far more slowly as n increases.

Why we ignore the "small stuff"

Big-O deliberately ignores constant multipliers and lower-order details, focusing purely on how growth behaves for very large inputs. An algorithm that takes exactly 5n steps and one that takes exactly 3n+100 steps are both simply called O(n) β€” because for sufficiently large n, both are overwhelmingly dominated by their proportionality to n, and the specific constants become comparatively irrelevant to the algorithm's fundamental scaling behaviour.

Common growth rates, from best to worst

  • O(1) β€” constant time: same speed regardless of input size (like looking up a value by direct array index)
  • O(log n) β€” logarithmic: grows very slowly (binary search)
  • O(n) β€” linear: doubles when input doubles (checking every item once)
  • O(n log n) β€” the best achievable for general-purpose comparison-based sorting algorithms
  • O(nΒ²) β€” quadratic: quadruples when input doubles (comparing every pair of items)
  • O(2ⁿ) β€” exponential: becomes catastrophically, unusably slow even for modest input sizes

Formal definition and analysis techniques

Formal definition

f(n) = O(g(n)) means there exist positive constants C and nβ‚€ such that f(n) ≀ CΒ·g(n) for all n β‰₯ nβ‚€. In words: eventually (once n is large enough), f(n) is bounded above by some constant multiple of g(n). This precisely formalises the intuitive idea of "f doesn't grow faster than g, in the long run, up to a constant factor."

Related notations

Big-O (O) describes an upper bound on growth. Big-Omega (Ξ©) describes a lower bound. Big-Theta (Θ) describes a tight bound β€” both upper and lower simultaneously, meaning the algorithm's actual growth rate is precisely known, not merely bounded from one side. In casual usage, "Big-O" is often used loosely to mean any of these, but rigorous computer science texts distinguish them carefully.

Worst-case, average-case, and best-case analysis

An algorithm's running time can depend heavily on the specific input given, not just its size. Worst-case analysis (the most common standard) bounds the maximum possible time over all inputs of a given size β€” providing a reliable guarantee. Average-case analysis considers the expected time over some assumed distribution of typical inputs. Best-case analysis (least commonly emphasised, since it provides the weakest practical guarantee) considers the most favourable possible input.

Analysing a simple algorithm β€” linear search

Checking each of n items one at a time to find a target value: in the worst case (target is last, or absent entirely), this requires n comparisons β€” O(n). In the best case (target is first), it requires just 1 comparison β€” O(1). The standard, most commonly cited complexity for linear search is the worst-case bound, O(n).

Sorting algorithm comparison

AlgorithmAverage caseWorst case
Bubble sortO(nΒ²)O(nΒ²)
Merge sortO(n log n)O(n log n)
QuicksortO(n log n)O(nΒ²)

Despite quicksort's theoretically worse worst-case bound, it is frequently used in practice because its average-case performance and constant-factor efficiency are excellent for typical real-world data.

Historical origins, P vs NP, and the limits of asymptotic analysis

Historical origins in number theory

Big-O notation was introduced not by computer scientists but by German number theorist Paul Bachmann in 1894, in a book on analytic number theory, studying the growth rates of number-theoretic functions. It was popularised and extended by Edmund Landau shortly afterward (hence sometimes called "Landau notation"), and only decades later, following Donald Knuth's influential adoption and systematisation of the notation in his seminal series The Art of Computer Programming (beginning 1968), did it become the near-universal standard language of computational complexity analysis in computer science.

Complexity classes β€” P and NP

Big-O notation is the essential language used to define formal complexity classes. A problem is in class P ("polynomial time") if it can be solved by an algorithm with worst-case running time O(nᡏ) for some fixed constant k β€” considered the mathematical formalisation of "efficiently solvable." A problem is in class NP ("nondeterministic polynomial time") if a proposed solution can be verified in polynomial time, even if finding that solution in the first place might require far longer. The famous, unsolved P vs NP question (one of the seven Clay Millennium Prize Problems β€” see the Hilbert's 23 Problems entry) asks whether every problem whose solution can be quickly verified can also always be quickly solved β€” a question with profound implications for cryptography, optimization, and the theoretical limits of computation, remaining completely open as of 2026.

Amortised analysis

Some data structures have operations that are occasionally expensive but, on average across a long sequence of operations, remain cheap overall. Amortised analysis (formalised significantly by Robert Tarjan in the 1980s) rigorously bounds the average cost per operation across an entire sequence, even when individual operations vary considerably in cost β€” a classic example being a dynamically resizing array, where occasional expensive resize operations are more than compensated for by many subsequent cheap insertions, giving an amortised O(1) cost per insertion overall despite occasional O(n) worst-case individual operations.

What Big-O deliberately does NOT tell you

Big-O analysis focuses purely on asymptotic (very large n) behaviour and deliberately ignores constant factors β€” meaning an algorithm with a smaller Big-O complexity class can nonetheless be genuinely slower in practice for realistic, moderate input sizes, if it carries a sufficiently large hidden constant factor or significant additional overhead. Real-world engineering practice must therefore always carefully balance rigorous asymptotic Big-O analysis against empirical, real-world benchmarking on realistic and representative data β€” Big-O provides essential theoretical guidance, but is deliberately not the complete practical picture on its own.

πŸ“š Sources

Tier 1 Cormen, T.H., Leiserson, C.E., Rivest, R.L. and Stein, C. (2022). Introduction to Algorithms. 4th ed. MIT Press. β€” Standard algorithms textbook.
Tier 1 Knuth, D.E. (1976). Big Omicron and big Omega and big Theta. ACM SIGACT News, 8(2), 18–24. β€” Standardisation of the notation for computer science.
Tier 2 Sipser, M. (2012). Introduction to the Theory of Computation. 3rd ed. Cengage Learning.
Tier 3 Fortnow, L. (2013). The Golden Ticket: P, NP, and the Search for the Impossible. Princeton University Press.

πŸ”— Related entries

Entry v1.0 Β· Added 2026-05-27 Β· Discrete Mathematics Β· Concept JSON Markdown Status