Growth Functions

Algorithmics study and revision notes

Jaak Vilo

2026-08-22

Why growth matters

An algorithm that works on a small example may become unusable when its input grows. Growth analysis asks how required work, memory, communication, or another resource depends on the size and shape of the input. It supports machine-independent comparison while deliberately ignoring many implementation details.

Asymptotic analysis and measurement are complementary. Analysis explains long-run scaling under a model; experiments reveal constants, memory behaviour, compiler effects, and the input range that matters in practice.

Learning goals

After studying this note, you should be able to:

Prerequisites

You should understand basic algebra, functions, powers, logarithms, loops, arrays, and recursion. The preceding orientation note introduced inputs, representations, and the unit-cost RAM model.

Input size and cost models

Before counting work, decide what the input size means. For sorting, nn is normally the number of records. A graph may require two parameters, |V||V| and |E||E|. A matrix multiplication involves dimensions, not merely one generic nn. For an integer xx, the representation length is log2x+1\lfloor\log_2 x\rfloor+1 bits when x>0x>0.

This last distinction prevents misleading claims. An algorithm taking O(x)O(x) steps is exponential in the bit length of xx, not polynomial in it. Such a bound is often called pseudo-polynomial when it is polynomial in numeric values but not in the length of their encoding.

A cost model states which operations are counted. Possibilities include comparisons, array accesses, arithmetic operations on machine words, allocated words, block transfers, messages, or calls to an expensive subroutine. A result is meaningful only together with its model.

Cases, probability, and sequences

Inputs of the same size can produce different costs:

These expectations are not interchangeable. “Random-looking test data” is not a mathematical input distribution, and random pivot selection is not an assumption that the original input is random.

Amortised analysis uses no probability. It bounds the total cost of every allowed operation sequence and assigns that total across the operations. A single operation may remain expensive even when the amortised cost per operation is small.

Each of these labels applies to a cost function, not directly to a line of code. State the size parameter first, then say which inputs or random choices the function quantifies over.

From code to a cost function

Count executions rather than multiplying visible loop bounds mechanically. Consider:

for i = 1 to n:
    for j = 1 to i:
        do constant work

The number of executions of the inner operation is

i=1ni=n(n+1)2 \sum_{i=1}^{n}i=\frac{n(n+1)}{2}

Therefore the running time is Θ(n2)\Theta(n^2). Two nested loops happen to give a quadratic result here, but the sum explains why; if the inner bound were logi\lfloor\log i\rfloor, the result would be different.

Consecutive phases add. Nested independent work usually multiplies. Conditional branches require a case assumption: a worst-case analysis uses the most costly feasible branch, while an expected analysis needs probabilities.

A small mathematical toolkit

Several sums recur throughout algorithm analysis:

i=1n1=n,i=1ni=n(n+1)2=Θ(n2), \sum_{i=1}^{n}1=n, \qquad \sum_{i=1}^{n}i=\frac{n(n+1)}{2}=\Theta(n^2),

i=0k2i=2k+11,i=1n1i=Θ(logn). \sum_{i=0}^{k}2^i=2^{k+1}-1, \qquad \sum_{i=1}^{n}\frac1i=\Theta(\log n).

The geometric series explains dynamic-array resizing and levels of complete trees. The harmonic sum appears in probabilistic analyses.

Useful logarithm rules are

log(xy)=logx+logy,log(xa)=alogx, \log(xy)=\log x+\log y, \qquad \log(x^a)=a\log x,

and

logbn=loganlogab. \log_b n=\frac{\log_a n}{\log_a b}.

Changing a fixed logarithm base multiplies by a constant, so the base normally disappears inside asymptotic notation.

Asymptotic definitions

Assume ff and gg are non-negative for sufficiently large nn. Formally, O(g)O(g) is a set of functions. The notation fO(g)f\in O(g) is therefore clearest, although textbooks conventionally write f=O(g)f=O(g) as one-way shorthand. It is not an algebraic equality: from f=O(g)f=O(g) one may not infer g=O(f)g=O(f).

Upper, lower, and tight bounds

We have fO(g)f\in O(g) if constants c>0c>0 and n0n_0 exist such that

0f(n)cg(n)for all nn0. 0\le f(n)\le c g(n) \quad\text{for all }n\ge n_0.

We have fΩ(g)f\in\Omega(g) if constants c>0c>0 and n0n_0 exist such that

0cg(n)f(n)for all nn0. 0\le c g(n)\le f(n) \quad\text{for all }n\ge n_0.

Finally, fΘ(g)f\in\Theta(g) when both bounds hold. Equivalently, positive c1,c2,n0c_1,c_2,n_0 exist with

0c1g(n)f(n)c2g(n)for all nn0. 0\le c_1g(n)\le f(n)\le c_2g(n) \quad\text{for all }n\ge n_0.

Worst case says which cost function is under discussion; Big O says how a function is bounded. Big O does not itself mean worst case.

Strict asymptotic relations

We have fo(g)f\in o(g) if, for every constant c>0c>0, some n0n_0 makes

0f(n)<cg(n)for all nn0. 0\le f(n)<c g(n) \quad\text{for all }n\ge n_0.

Thus ff becomes smaller than every positive constant multiple of gg. Conversely, fω(g)f\in\omega(g) if, for every c>0c>0, eventually f(n)>cg(n)f(n)>c g(n).

When g(n)>0g(n)>0 eventually and the relevant limit exists,

limnf(n)g(n)=0 \lim_{n\to\infty}\frac{f(n)}{g(n)}=0

implies fo(g)f\in o(g). A finite positive limit implies fΘ(g)f\in\Theta(g), and an infinite limit implies fω(g)f\in\omega(g). The constant-based definitions still apply when a ratio limit does not exist.

Worked proof from the definition

Let f(n)=3n2+7n+20f(n)=3n^2+7n+20. For every n1n\ge1,

3n2+7n+203n2+7n2+20n2=30n2. 3n^2+7n+20\le3n^2+7n^2+20n^2=30n^2.

Choosing c2=30c_2=30 and n0=1n_0=1 proves fO(n2)f\in O(n^2). Also f(n)3n2f(n)\ge3n^2, so c1=3c_1=3 and n0=1n_0=1 prove fΩ(n2)f\in\Omega(n^2). Hence

3n2+7n+20Θ(n2). 3n^2+7n+20\in\Theta(n^2).

The constants need only work eventually; they need not be smallest possible.

Common growth classes

For fixed k>1k>1, a>1a>1, and d>1d>1,

1logn(logn)knnlognndann!. 1\prec\log n\prec(\log n)^k\prec n\prec n\log n \prec n^d\prec a^n\prec n!.

Here fgf\prec g informally denotes fo(g)f\in o(g). The condition d>1d>1 is essential: for d=1d=1, nlognn\log n grows faster than nd=nn^d=n.

Growth Informal name Typical source
Θ(1)\Theta(1) constant one indexed array access
Θ(logn)\Theta(\log n) logarithmic repeatedly halve a range
Θ(n)\Theta(n) linear inspect every item once
Θ(nlogn)\Theta(n\log n) linearithmic balanced divide and conquer
Θ(n2)\Theta(n^2) quadratic inspect every pair
Θ(2n)\Theta(2^n) exponential enumerate all subsets
Θ(n!)\Theta(n!) factorial enumerate all permutations

Dominant terms determine a sum’s asymptotic class when terms are eventually non-negative. Thus

n3+100nlogn+106Θ(n3). n^3+100n\log n+10^6\in\Theta(n^3).

This does not make lower-order terms or constants irrelevant at finite sizes.

Recurrences from first principles

A recurrence describes a recursive call tree. It must include a base case. For powers of two, consider

T(1)=d,T(n)=2T(n/2)+cn(n>1). T(1)=d, \qquad T(n)=2T(n/2)+cn \quad(n>1).

At level ii, there are 2i2^i subproblems of size n/2in/2^i. Their non-recursive work totals

2icn2i=cn. 2^i c\frac{n}{2^i}=cn.

There are log2n\log_2 n non-leaf levels, plus nn constant-cost leaves. Therefore

T(n)=cnlog2n+dn=Θ(nlogn). T(n)=cn\log_2 n+dn=\Theta(n\log n).

For arbitrary nn, floors and ceilings change constants but not this asymptotic result. A later note gives the Master theorem; expanding a few levels first is safer than applying a memorised formula to a recurrence that does not fit it.

Worked comparison: constants versus growth

Suppose two implementations are modelled by

TA(n)=50nlog2n,TB(n)=n2. T_A(n)=50n\log_2 n, \qquad T_B(n)=n^2.

Although TAo(TB)T_A\in o(T_B), A is faster only when 50log2n<n50\log_2n<n. At n=128n=128, the left side is 350350, so B wins in this model. At n=512n=512, it is 450450, so A wins. Asymptotic order predicts eventual behaviour; an exact model or measurement locates the relevant crossover.

Time, space, and trade-offs

Analyse different resources separately. Iteratively summing an array takes Θ(n)\Theta(n) time and Θ(1)\Theta(1) auxiliary space. A direct recursive version still takes Θ(n)\Theta(n) time but uses Θ(n)\Theta(n) call-stack space. An algorithm may deliberately spend memory to save recomputation, or spend time to reduce storage.

Also distinguish auxiliary space from total storage. If an input array already occupies Θ(n)\Theta(n) words, saying an in-place scan uses Θ(1)\Theta(1) auxiliary space does not mean the entire computation occupies constant memory.

Measurement and asymptotic analysis

A useful timing experiment should:

A straight line on a log-log plot can suggest polynomial growth, with its slope suggesting an exponent. It cannot prove an asymptotic bound: measurements cover finitely many inputs, and different functions can look similar over a restricted range.

Connections

Common mistakes

Self-check

  1. Prove 7n+4Θ(n)7n+4\in\Theta(n) with explicit constants.
  2. Is nO(n2)n\in O(n^2)? Is n2O(n)n^2\in O(n)? Explain from the definition.
  3. Why is writing fO(g)f\in O(g) conceptually clearer than f=O(g)f=O(g)?
  4. Distinguish worst-case, average-case, randomized expected, and amortised cost.
  5. Order (logn)2(\log n)^2, nlognn\log n, n2+100nn^2+100n, n3n^3, and 2n2^n.
  6. What is the bit length of a positive integer xx, asymptotically?
  7. Why does every level of T(n)=3T(n/3)+nT(n)=3T(n/3)+n contribute Θ(n)\Theta(n) non-recursive work?
  8. Give an algorithm whose iterative and recursive forms have equal time but different space costs.

Revision summary

Implementations and hands-on exploration

Small experiments

  1. Instrument the triangular nested loop. After outer iteration ii, assert the exact invariant count == i*(i+1)/2; for n=2kn=2^k, also print count/n^2 and count/n. Which ratio approaches a constant?
  2. For powers of two, implement dummy work whose counters execute exactly 50nlog2n50n\log_2 n and n2n^2 operations. Assert both counts before timing the loops, then compare the analytical and measured crossover points and explain any difference.

Sources and further study

See the chapters on growth of functions and analysing algorithms in Cormen et al. (2022), and the introductory algorithm-analysis discussion in Kleinberg and Tardos (2006).

References

Cormen, Thomas H., Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. 2022. Introduction to Algorithms. 4th ed. MIT Press.
Kleinberg, Jon, and Éva Tardos. 2006. Algorithm Design. Pearson.