Complexity Analysis
Level: 4 — Application (novel problems, no hints) Time Limit: 60 minutes Total Marks: 50
Q1. [10 marks] A programmer writes a function on an array of size :
process(A, n):
if n <= 1: return
for i in 0..n-1: # loop L1
for j in 0..i: # loop L2
visit(A[j])
process(A, n/3)
process(A, n/3)
(a) Write the recurrence for the running time in terms of the work done at each level and the recursive calls. [3]
(b) Solve using the Master Theorem, stating , , and , and identifying which case applies. [5]
(c) Give the tight bound. [2]
Q2. [12 marks] Consider a dynamic array (initially capacity 1) that doubles its capacity when full, but on each doubling it copies all existing elements. Additionally, whenever the array becomes exactly one-quarter full after deletions, it halves its capacity (copying survivors).
(a) Using the aggregate method, prove that a sequence of push operations (no deletions) costs total, and state the amortized cost per push. [5]
(b) Using the accounting method, assign a charge per push that pays for future copies. State the charge and justify it covers all copy work. [4]
(c) Explain in one or two sentences why the quarter-full (rather than half-full) shrink threshold prevents amortized cost from thrashing between grow and shrink. [3]
Q3. [10 marks] Prove the following statements directly from the formal definition of the asymptotic notations (produce explicit constants where required).
(a) Prove by exhibiting constants and . [3]
(b) Prove with explicit , . [3]
(c) Hence conclude , and prove that for any fixed constant . [4]
Q4. [10 marks] Solve the recurrence using the recursion tree method, then verify by substitution:
(a) Draw/describe the recursion tree: cost per level, number of levels, and total cost. [6]
(b) Verify your answer by the substitution method (guess and find a valid ). [4]
Q5. [8 marks]
For the algorithm below (searching for a target x in an unsorted array of distinct elements, each equally likely to be the target and target guaranteed present):
linsearch(A, x):
for i in 0..n-1:
if A[i] == x: return i
(a) State best-case and worst-case comparison counts with a one-line justification each. [3]
(b) Derive the average-case number of comparisons exactly (closed form), assuming uniform position distribution. [3]
(c) State the auxiliary space complexity and the total space complexity, distinguishing them. [2]
Answer keyMark scheme & solutions
Q1 [10]
(a) Work in loops L1/L2: sum over of . Two recursive calls of size :
(b) Master theorem with , , . [1] Compare with . [2] Since and the regularity condition holds for , Case 3 applies. [2]
(c) . [2]
Q2 [12]
(a) Copies occur at sizes . Total copy work . Plus units for the pushes themselves. Total . [3] Amortized cost per push (a small constant, ). [2]
(b) Charge 3 per push: 1 for placing the element, 1 saved to move itself on the next copy, 1 saved to move an element that was moved for free previously. When array of size doubles, the elements added since the last doubling each carry 2 saved credits ⇒ credits, enough to copy all elements. [4]
(c) Halving only at quarter-full leaves the array half-full immediately after a shrink, so operations are required before either another grow or shrink is triggered — the copy cost is amortized over ops, avoiding thrashing (which a half-full shrink threshold would cause). [3]
Q3 [10]
(a) For : . So . [3]
(b) for all (extra terms positive). So . [3]
(c) Both and ⇒ . [2] For : (exponential beats any polynomial, provable by L'Hôpital times or ratio test). Hence no constants can bound for all large . [2]
Q4 [10]
(a) Root cost . Level has nodes each of size , cost per level . [2] Levels: . [1] Total . [2] So . [1]
(b) Guess . Then . Need . Take : holds. [4]
Q5 [8]
(a) Best case (target at index 0). Worst case (target at last index / not found early). [3]
(b) Average . [3]
(c) Auxiliary space (only loop index / return value). Total space (includes the input array). Distinction: auxiliary excludes input storage; total includes it. [2]
[
{"claim":"Q4 recursion tree geometric sum bounded by 4n, Theta(n)","code":"i=symbols('i'); S=summation((Rational(3,4))**i,(i,0,oo)); result=(S==4)"},
{"claim":"Q4 substitution constant c=4 satisfies 3c/4+1<=c","code":"c=4; result=(Rational(3,4)*c+1<=c)"},
{"claim":"Q5 average comparisons = (n+1)/2","code":"n=symbols('n',positive=True); k=symbols('k'); avg=summation(k,(k,1,n))/n; result=(simplify(avg-(n+1)/2)==0)"},
{"claim":"Q3a bound 3n^2+5n+2 <= 10n^2 for n>=1","code":"n=symbols('n',positive=True); expr=10*n**2-(3*n**2+5*n+2); result=(expr.subs(n,1)>=0) and (simplify(diff(expr,n)).subs(n,1)>0)"},
{"claim":"Q1 master case3: f=n^2 dominates n^(log_3 2)","code":"result=(2>log(2)/log(3))"}
]