Level 5 — MasteryComplexity Analysis

Complexity Analysis

75 minutes50 marksprintable — key stays hidden on paper

Level 5 — Mastery (cross-domain: mathematics + algorithm theory) Time limit: 75 minutes Total marks: 50

Answer all questions. Justify every claim; unproven assertions earn no marks. You may use standard results (Master Theorem, asymptotic identities) but must state them when invoked.


Question 1 — Formal proof & bounds (18 marks)

Let f(n)=3n2+5nlog2n+7f(n) = 3n^2 + 5n\log_2 n + 7 and g(n)=n2g(n) = n^2.

(a) Using the formal definition of Big-O, prove that f(n)=O(n2)f(n) = O(n^2) by exhibiting explicit constants c>0c > 0 and n01n_0 \ge 1 and verifying the inequality for all nn0n \ge n_0. (6)

(b) Prove that f(n)=Θ(n2)f(n) = \Theta(n^2) by additionally establishing the lower bound f(n)=Ω(n2)f(n) = \Omega(n^2). (4)

(c) A colleague claims 5nlog2n=O(n1.5)5n\log_2 n = O(n^{1.5}). Decide whether this is true or false and prove your answer rigorously (i.e. from the definition, using a limit argument). (4)

(d) State and prove that the relation "f=Θ(g)f = \Theta(g)" is an equivalence relation on the set of eventually-positive functions NR>0\mathbb{N} \to \mathbb{R}_{>0} (reflexivity, symmetry, transitivity). (4)


Question 2 — Recurrences via three methods (18 marks)

Consider the recurrence describing a divide-and-conquer routine: T(n)=2T ⁣(n2)+nlog2n,T(1)=1.T(n) = 2\,T\!\left(\frac{n}{2}\right) + n\log_2 n, \qquad T(1) = 1.

(a) Explain why the standard Master Theorem (the three-case version for T(n)=aT(n/b)+Θ(nc)T(n)=aT(n/b)+\Theta(n^c)) does not directly apply, and state which extended case (Case 2 with a log factor) is relevant. (3)

(b) Solve the recurrence exactly by the recursion-tree method: draw/describe the levels, give the work per level, count the levels, sum them, and conclude the asymptotic order of T(n)T(n). (7)

(c) Confirm your answer using the substitution method: guess T(n)=Θ(nlog2n)T(n) = \Theta(n\log^2 n) and prove the upper bound T(n)cnlog22nT(n) \le c\,n\log_2^2 n for a suitable constant cc and all nn0n \ge n_0 by induction. (6)

(d) For the decrease-by-a-constant recurrence S(n)=S(n1)+nS(n) = S(n-1) + n, with S(0)=0S(0)=0, give the closed form and its Θ\Theta class. (2)


Question 3 — Amortized analysis, cross-domain modelling (14 marks)

A dynamic array (vector) starts empty with capacity 1. On a push operation: if the array is full, its capacity doubles (copying all existing elements to new storage, costing 1 unit per element copied), then the new element is inserted (cost 1). If not full, insertion costs 1.

(a) Using the aggregate method, compute the total cost of nn consecutive push operations and hence the amortized cost per operation. Show the geometric-series step explicitly. (5)

(b) Re-derive the amortized cost using the accounting method: assign a charge c^\hat{c} to each push, prove the bank balance never goes negative, and state the amortized cost. (4)

(c) Using the potential method, define a potential function Φ(Di)\Phi(D_i) and show it yields the same amortized cost. Verify Φ(D0)=0\Phi(D_0)=0 and Φ(Di)0\Phi(D_i)\ge 0. (3)

(d) Physics analogy. A capacitor stores energy E=12CV2E=\tfrac12 C V^2; charging it draws current in bursts. Briefly explain (2–3 sentences) how the potential function Φ\Phi plays the role of "stored energy" in smoothing bursty costs, and why the average (amortized) rate is what matters for long-run performance. (2)


Answer keyMark scheme & solutions

Question 1

(a) f(n)=O(n2)f(n)=O(n^2) (6 marks)

Definition: f=O(g)f=O(g) iff c>0,n01\exists c>0, n_0\ge1 with 0f(n)cg(n)0\le f(n)\le c\,g(n) for all nn0n\ge n_0. (1)

For n1n\ge 1: log2nn\log_2 n \le n, so 5nlog2n5n25n\log_2 n \le 5n^2; also 77n27\le 7n^2. (2) Hence f(n)=3n2+5nlog2n+73n2+5n2+7n2=15n2.f(n)=3n^2+5n\log_2 n+7 \le 3n^2+5n^2+7n^2 = 15n^2. (2) Take c=15c=15, n0=1n_0=1. The inequality f(n)15n2f(n)\le 15n^2 holds for all n1n\ge1, proving f=O(n2)f=O(n^2). (1)

(b) Ω\Omega and hence Θ\Theta (4 marks)

Since all terms of ff are positive for n1n\ge1, f(n)3n2f(n)\ge 3n^2. (2) Thus with c=3c'=3, n0=1n_0=1: f(n)3n2f(n)\ge 3n^2, giving f=Ω(n2)f=\Omega(n^2). (1) f=O(n2)f=O(n^2) and f=Ω(n2)f=\Omega(n^2) f=Θ(n2)\Rightarrow f=\Theta(n^2). (1)

(c) Is 5nlog2n=O(n1.5)5n\log_2 n = O(n^{1.5})? — FALSE (4 marks)

Consider limn5nlog2nn1.5=limn5log2nn0.5.\lim_{n\to\infty}\frac{5n\log_2 n}{n^{1.5}}=\lim_{n\to\infty}\frac{5\log_2 n}{n^{0.5}}. (2) As nn\to\infty, log2n\log_2 n grows slower than any positive power, so log2nn0\dfrac{\log_2 n}{\sqrt n}\to 0. (1)

Wait — this limit is 00, which would make it TRUE. Correct evaluation: log2n=o(n0.5)\log_2 n = o(n^{0.5}), so nlog2n=o(n1.5)n\log_2 n = o(n^{1.5}), hence 5nlog2n=O(n1.5)5n\log_2 n = O(n^{1.5}) is TRUE. (1 for correct conclusion)

Correct conclusion: the claim is TRUE. The limit above tends to 00, so 5nlog2no(n1.5)O(n1.5)5n\log_2 n\in o(n^{1.5})\subseteq O(n^{1.5}). Full marks require identifying the limit =0=0 and concluding TRUE.

(d) Θ\Theta is an equivalence relation (4 marks)

Write fgf\sim g for f=Θ(g)f=\Theta(g).

  • Reflexive: f(n)1f(n)f(n)\le 1\cdot f(n) and f(n)1f(n)f(n)\ge 1\cdot f(n), so f=Θ(f)f=\Theta(f). (1)
  • Symmetric: f=Θ(g)f=\Theta(g) means c1gfc2gc_1 g\le f\le c_2 g eventually. Dividing: 1c2fg1c1f\frac1{c_2}f\le g\le \frac1{c_1}f, so g=Θ(f)g=\Theta(f). (1.5)
  • Transitive: if c1gfc2gc_1 g\le f\le c_2 g (for nn1n\ge n_1) and d1hgd2hd_1 h\le g\le d_2 h (for nn2n\ge n_2), then for nmax(n1,n2)n\ge\max(n_1,n_2): c1d1hfc2d2hc_1 d_1 h \le f \le c_2 d_2 h, so f=Θ(h)f=\Theta(h). (1.5)

Question 2

(a) Why Master Theorem stalls (3 marks) Here a=2a=2, b=2b=2, so nlogba=nlog22=nn^{\log_b a}=n^{\log_2 2}=n. The driving term is f(n)=nlog2nf(n)=n\log_2 n, which is not Θ(nc)\Theta(n^c) for any constant cc: it lies between nn and n1+εn^{1+\varepsilon}. (2) The polynomial three-case version fails; we use the extended Case 2: if f(n)=Θ(nlogbalogkn)f(n)=\Theta(n^{\log_b a}\log^k n) then T(n)=Θ(nlogbalogk+1n)T(n)=\Theta(n^{\log_b a}\log^{k+1}n). Here k=1k=1. (1)

(b) Recursion tree (7 marks) Root work: nlog2nn\log_2 n. (1) At depth ii there are 2i2^i nodes, each of size n/2in/2^i; work per node =n2ilog2n2i=\frac{n}{2^i}\log_2\frac{n}{2^i}. (2) Total work at level ii: 2in2ilog2n2i=n(log2ni).2^i\cdot\frac{n}{2^i}\log_2\frac{n}{2^i}=n\bigl(\log_2 n - i\bigr). (2) Number of levels: n/2L=1L=log2nn/2^L=1\Rightarrow L=\log_2 n. Summing i=0i=0 to log2n1\log_2 n-1: i=0log2n1n(log2ni)=nj=1log2nj=nlog2n(log2n+1)2=Θ(nlog22n).\sum_{i=0}^{\log_2 n-1} n(\log_2 n - i)=n\sum_{j=1}^{\log_2 n} j = n\cdot\frac{\log_2 n(\log_2 n+1)}{2}=\Theta(n\log_2^2 n). (2) (The leaf level contributes Θ(n)\Theta(n), dominated.) Conclusion: T(n)=Θ(nlog22n)T(n)=\Theta(n\log_2^2 n).

(c) Substitution — upper bound (6 marks) Guess T(n)cnlog22nT(n)\le c\,n\log_2^2 n. Inductive step, assuming it for n/2n/2: T(n)=2T(n/2)+nlog2n2cn2log22 ⁣n2+nlog2n=cn(log2n1)2+nlog2n.T(n)=2T(n/2)+n\log_2 n \le 2c\frac n2\log_2^2\!\frac n2 + n\log_2 n = c\,n(\log_2 n-1)^2+n\log_2 n. (2) Expand: cn(log22n2log2n+1)+nlog2n=cnlog22n2cnlog2n+cn+nlog2n.c\,n(\log_2^2 n - 2\log_2 n + 1)+n\log_2 n = c\,n\log_2^2 n - 2c\,n\log_2 n + c\,n + n\log_2 n. (2) This is cnlog22n\le c\,n\log_2^2 n provided 2cnlog2n+cn+nlog2n0    (12c)log2n+c0.-2c\,n\log_2 n + c\,n + n\log_2 n \le 0 \iff (1-2c)\log_2 n + c \le 0. For c1c\ge 1 this holds for all n2n\ge 2 (since 12c<01-2c<0 and the log\log term dominates). Take c=1c=1, n0=2n_0=2; base case T(2)=2T(1)+2=4121=2T(2)=2T(1)+2=4\le 1\cdot2\cdot1=2 fails, so pick c=2c=2 giving c21=44c\cdot2\cdot1=4\ge4. ✓ (2) Hence T(n)=O(nlog22n)T(n)=O(n\log_2^2 n), matching the tree bound.

(d) Decrease-by-constant (2 marks) S(n)=k=1nk=n(n+1)2=Θ(n2)S(n)=\sum_{k=1}^n k=\frac{n(n+1)}2=\Theta(n^2). (2)


Question 3

(a) Aggregate method (5 marks) Insertions cost 11 each: total nn. (1) Doublings occur when size hits 1,2,4,1,2,4,\dots; copy costs are 1+2+4++2log2(n1)<2log2n2n1+2+4+\cdots+2^{\lfloor\log_2(n-1)\rfloor} < 2^{\lceil\log_2 n\rceil}\le 2n. (2) Geometric series: k=0log2n2k=2log2n+11<2n\sum_{k=0}^{\lfloor\log_2 n\rfloor}2^k = 2^{\lfloor\log_2 n\rfloor+1}-1 < 2n. (1) Total cost <n+2n=3n< n+2n=3n, so amortized cost <3n/n=3=O(1)<3n/n=3=O(1). (1)

(b) Accounting method (4 marks) Charge c^=3\hat c=3 per push. (1) Actual insertion uses 1; store 2 credits on the newly inserted element (and, effectively, the "just-copied" region). (1) When the array of size mm doubles, the mm elements copied were each charged 2 extra credits since the previous doubling, which exactly pays the mm copy operations. (1) Balance never negative \Rightarrow amortized cost =3=O(1)=3=O(1). (1)

(c) Potential method (3 marks) Define Φ(Di)=2(size)(capacity)\Phi(D_i)=2\cdot(\text{size}) - (\text{capacity}). (1) Then Φ(D0)=0\Phi(D_0)=0 (size 0, cap... take convention Φ=0\Phi=0 initially) and Φ0\Phi\ge0 since after any doubling size \ge capacity/2 so 2sizecapacity2\,\text{size}\ge\text{capacity}. (1) Amortized cost c^i=ci+Φ(Di)Φ(Di1)\hat c_i=c_i+\Phi(D_i)-\Phi(D_{i-1}): non-doubling push: ci=1c_i=1, size+1+1 so ΔΦ=2\Delta\Phi=2, total 33. Doubling push (size mm+1m\to m{+}1, cap m2mm\to2m): ci=m+1c_i=m+1, ΔΦ=(2(m+1)2m)(2mm)=2m\Delta\Phi=(2(m{+}1)-2m)-(2m-m)=2-m, total =m+1+2m=3=m+1+2-m=3. (1) Consistent O(1)O(1).

(d) Physics analogy (2 marks) Φ\Phi acts like stored potential/elastic energy: cheap operations "charge up" Φ\Phi (like charging a capacitor storing 12CV2\tfrac12CV^2), and the rare expensive resize "discharges" it, so the stored energy pays for the burst. (1) Because the potential's contributions telescope, the long-run amortized (average) rate is O(1)O(1) — the relevant metric for sustained throughput, just as average power, not instantaneous surge current, governs long-run behaviour. (1)


[
  {"claim":"f(n)=3n^2+5n log2 n+7 <= 15 n^2 for n=1..1000","code":"import sympy as sp\nok=all(3*n**2+5*n*sp.log(n,2)+7 <= 15*n**2 for n in range(1,1001))\nresult=bool(ok)"},
  {"claim":"limit of 5 log2 n / sqrt(n) is 0 (so 5 n log2 n = O(n^1.5))","code":"n=sp.symbols('n',positive=True)\nL=sp.limit(5*sp.log(n,2)/n**sp.Rational(1,2),n,sp.oo)\nresult=(L==0)"},
  {"claim":"recursion tree sum n*sum_{j=1}^{L} j equals n*L*(L+1)/2","code":"n,L=sp.symbols('n L',positive=True)\nj=sp.symbols('j')\nlhs=n*sp.summation(j,(j,1,L))\nresult=bool(sp.simplify(lhs - n*L*(L+1)/2)==0)"},
  {"claim":"S(n)=sum k = n(n+1)/2","code":"n=sp.symbols('n',positive=True,integer=True)\nk=sp.symbols('k')\nresult=bool(sp.simplify(sp.summation(k,(k,1,n)) - n*(n+1)/2)==0)"},
  {"claim":"aggregate doubling copies: sum_{k=0}^{m} 2^k = 2^(m+1)-1 < 2*2^m","code":"m=sp.symbols('m',nonnegative=True,integer=True)\nk=sp.symbols('k')\ns=sp.summation(2**k,(k,0,m))\nresult=bool(sp.simplify(s-(2**(m+1)-1))==0)"}
]