∑GATE DA Atlas

Algorithm Analysis — Asymptotic Notation and Recurrences

Measuring running time by counting operations, best/worst/average cases, Big-O, Ω and Θ with their properties, the growth-rate hierarchy, counting loops (nested, logarithmic, dependent), solving recurrences by substitution, recursion trees and the master theorem, amortised analysis, and space complexity.

Section 49 practice questions

What we measure

Running time is measured by counting basic operations (comparisons, assignments, arithmetic) as a function of the input size nn, ignoring machine-dependent constants.

  • Worst case: maximum over all inputs of size nn (the usual guarantee).
  • Best case: minimum (e.g. insertion sort on sorted input: n−1n - 1 comparisons).
  • Average case: expectation over a distribution of inputs (quicksort: ≈1.39 nlog⁡2n\approx 1.39\,n\log_2 n comparisons on random input).

Asymptotic notation

NotationMeaningInformally
f=O(g)f = O(g)∃c,n0:f(n)≤c g(n) ∀n≥n0\exists c, n_0: f(n) \le c\,g(n)\ \forall n \ge n_0ff grows at most like gg
f=Ω(g)f = \Omega(g)∃c,n0:f(n)≥c g(n) ∀n≥n0\exists c, n_0: f(n) \ge c\,g(n)\ \forall n \ge n_0at least like gg
f=Θ(g)f = \Theta(g)both OO and Ω\Omegaexactly like gg
f=o(g)f = o(g)f/g→0f/g \to 0strictly slower
f=ω(g)f = \omega(g)f/g→∞f/g \to \inftystrictly faster

Properties: transitivity; O(f)+O(g)=O(max⁡(f,g))O(f) + O(g) = O(\max(f, g)); constants and lower-order terms vanish (3n2+10nlog⁡n+7=Θ(n2)3n^2 + 10n\log n + 7 = \Theta(n^2)); logarithm bases differ by constants (log⁡2n=Θ(log⁡10n)\log_2 n = \Theta(\log_{10}n)), but exponential bases do not (2n≠Θ(3n)2^n \ne \Theta(3^n)).

Limit test: if lim⁡f/g=c\lim f/g = c with 0<c<∞0 < c < \infty, then f=Θ(g)f = \Theta(g); if the limit is 0, f=o(g)f = o(g).

The growth hierarchy

1≪log⁡log⁡n≪log⁡n≪n≪n≪nlog⁡n≪n2≪n3≪2n≪n!≪nn1 \ll \log\log n \ll \log n \ll \sqrt n \ll n \ll n\log n \ll n^2 \ll n^3 \ll 2^n \ll n! \ll n^n
nnlog⁡2n\log_2 nnlog⁡2nn\log_2 nn2n^22n2^n
103.3331001024
10001010410^410610^6≈10301\approx 10^{301}
10610^6202×1072\times10^7101210^{12}—

Counting loops

Loop shapeIterations
for i in range(n)nn
nested for i in range(n): for j in range(n)n2n^2
for i in range(n): for j in range(i)n(n−1)2\frac{n(n-1)}{2}
i = 1; while i < n: i *= 2⌈log⁡2n⌉\lceil\log_2 n\rceil
i = n; while i > 0: i //= 2⌊log⁡2n⌋+1\lfloor\log_2 n\rfloor + 1
for i in range(n): j = 1; while j < n: j *= 2nlog⁡nn\log n
i = 1; while i * i <= n: i += 1n\sqrt n

Recurrences

Recursive algorithms give recurrences. Three ways to solve them:

1. Unrolling / substitution: T(n)=T(n−1)+c⇒T(n)=cnT(n) = T(n-1) + c \Rightarrow T(n) = cn; T(n)=2T(n−1)+c⇒Θ(2n)T(n) = 2T(n-1) + c \Rightarrow \Theta(2^n) (Towers of Hanoi: 2n−12^n - 1 moves).

2. Recursion tree: sum the work level by level.

n n/2 n/2 n/4 n/4 n/4 n/4 nnn log₂ n levels × n work per level = Θ(n log n)
Each level of merge sort's recursion tree does n total work.

3. Master theorem for T(n)=aT(n/b)+f(n)T(n) = aT(n/b) + f(n) with a≥1a \ge 1, b>1b > 1. Compare f(n)f(n) with nlog⁡ban^{\log_b a}:

CaseConditionT(n)T(n)
1f(n)=O(nlog⁡ba−ϵ)f(n) = O(n^{\log_b a - \epsilon}) (leaves dominate)Θ(nlog⁡ba)\Theta(n^{\log_b a})
2f(n)=Θ(nlog⁡balog⁡kn)f(n) = \Theta(n^{\log_b a}\log^k n), k≥0k \ge 0 (balanced)Θ(nlog⁡balog⁡k+1n)\Theta(n^{\log_b a}\log^{k+1}n)
3f(n)=Ω(nlog⁡ba+ϵ)f(n) = \Omega(n^{\log_b a + \epsilon}) and af(n/b)≤cf(n)af(n/b) \le cf(n), c<1c < 1 (root dominates)Θ(f(n))\Theta(f(n))

Recurrences worth memorising

RecurrenceSolutionAlgorithm
T(n)=T(n/2)+1T(n) = T(n/2) + 1Θ(log⁡n)\Theta(\log n)binary search
T(n)=T(n−1)+1T(n) = T(n-1) + 1Θ(n)\Theta(n)linear recursion, linear search
T(n)=2T(n/2)+1T(n) = 2T(n/2) + 1Θ(n)\Theta(n)tree traversal
T(n)=2T(n/2)+nT(n) = 2T(n/2) + nΘ(nlog⁡n)\Theta(n\log n)merge sort, balanced quicksort
T(n)=T(n−1)+nT(n) = T(n-1) + nΘ(n2)\Theta(n^2)worst-case quicksort, selection sort
T(n)=2T(n−1)+1T(n) = 2T(n-1) + 1Θ(2n)\Theta(2^n)Towers of Hanoi
T(n)=T(n−1)+T(n−2)+1T(n) = T(n-1) + T(n-2) + 1Θ(φn)\Theta(\varphi^n), φ≈1.618\varphi \approx 1.618naive Fibonacci
T(n)=T(n)+1T(n) = T(\sqrt n) + 1Θ(log⁡log⁡n)\Theta(\log\log n)

Amortised analysis

The average cost per operation over a worst-case sequence of operations. Example: a dynamic array (Python list) doubles its capacity when full; a single append may cost O(n)O(n) for copying, but nn appends cost O(n)O(n) in total, so each is amortised O(1)O(1).

Space complexity

Extra memory used besides the input: merge sort O(n)O(n), quicksort O(log⁡n)O(\log n) expected for the recursion stack, heapsort and insertion sort O(1)O(1). Recursion depth counts as space.

Quick revision

Practice questions

GATE-style questions: 4 one-mark and 5 two-mark. Wrong MCQs cost ⅓ of their marks in the real exam; MSQ and NAT have no negative marking. Attempt each before opening the solution.

Q1MCQ1 mark

The recurrence T(n)=2T(n/2)+nT(n) = 2T(n/2) + n solves to

Q2MCQ1 mark

The recurrence T(n)=T(n/2)+cT(n) = T(n/2) + c (binary search) solves to

Q3NAT2 marks

What does this program print?

Python
count = 0
i = 1
while i < 100:
    i *= 2
    count += 1
print(count)
Q4MSQ2 marks

Which of the following are true?

One or more options are correct.

Q5NAT2 marks

What does this program print?

Python
c = 0
for i in range(10):
    for j in range(i, 10):
        c += 1
print(c)
Q6MCQ1 mark

The recurrence T(n)=T(n−1)+nT(n) = T(n - 1) + n, T(1)=1T(1) = 1 solves to

Q7MCQ2 marks

The recurrence T(n)=3T(n/2)+nT(n) = 3T(n/2) + n solves to

Q8MCQ1 mark

Which ordering of growth rates (slowest to fastest) is correct?

Q9NAT2 marks

T(n)=2T(n/2)+1T(n) = 2T(n/2) + 1 with T(1)=1T(1) = 1. The value of T(8)T(8) is ______.