ADS · Exam 20 Jul
Algorithms & Data Structures · SS26

Reason it out.
Write it for marks.

A source-aligned, exam-first studybook for Alex. It teaches the calculations and hand-written reasoning the examiner repeatedly rewards, then connects them to code and unfamiliar variants.

Exam: 20 July 20262–3 focused daysCasio fx‑991CW UK1 × A4 handwritten side5 days remaining
No matching section. Clear the search or switch off “Core only”.
Start here

Your single 2–3 day route

🔴 Exam-core The revision tutorials name the likely families; past exams show the examiner changes data, code, and wording. Learn a method you can execute on a fresh instance.

★ 19 July update: after a call with the professor, the priorities changed — read the prof briefing at the end of the book first. Strassen is OUT; Akra–Bazzi (easy integer p), full 15-pt ID3, applied Bloom, symmetric trees, hash chaining and the graph opener are IN.
Day 1 · 7 h
Must do: ID3 end to endBloom filter calculationsrecurrences, Master and Akra–Bazzi. Rework the source examples without looking. Finish with Mock Problem 2.
Day 2 · 7 h
Day 3 · 6 h
Must do: quantum breadthStrassen proof and recurrence → 90-minute mock. Mark it from the full solutions, then handwrite the A4 synthesis. If time: tree traversal/DP and hash probing drills. If only two days: skip slide-history, AI-development anecdotes, hardware/vendor material, exotic matrix algorithms and proof-heavy context.

What the evidence says

  • ID3: revision says “definitely”; repeated manual calculations across tutorials/exams.
  • Quantum: appeared in the last three exams with different questions; revision says prepare broadly.
  • New 2026 scope: selection, median-of-medians, Akra–Bazzi, probing and bucket sort were explicitly added/emphasized.
  • Latest pattern: choose 2 of 3 large problems; a problem mixes theory, calculation, code, and explanation.

How to use the Casio

Use the calculator for arithmetic, not as a substitute for written setup. For log₂x, enter ln(x) ÷ ln(2). Store repeated entropy terms in variables if useful. Keep at least 6 internal digits; round only the displayed final gain/probability to 3–4 decimals.

Sanity checks: entropy is in [0,1] for a binary label; information gain cannot be negative except tiny rounding; Bloom probability lies in [0,1]; integer k requires checking both neighbors.

Marks, not vibes

Write answers the examiner can award

90 min
2 of 3

The latest supplied exam says unsupported answers receive no credit. For every theorem or formula, write: name → parameters → applicability check → substitution → result → interpretation/check. For code: state the invariant, handle the empty/boundary case, update every pointer/size field, then give time and auxiliary-space complexity.

Suggested timing: 4 minutes scan and choose; 38 minutes per problem; 10 minutes check. If a calculation stalls, leave your setup—correct method earns partial credit.

Do not overfit to old questions. “New questions” most likely means new instances and combinations, not a new invisible syllabus. Practise transfer: change the dataset, the list length, the recurrence coefficients, or the graph source and re-run the method.
Chapter 1

Complexity: translate code into growth

🔴 Exam-core Complexity is the language used in almost every other chapter. Count how the dominant operation scales with input size; ignore hardware time and lower-order clutter.

Bounds you must distinguish

f(n) ∈ O(g(n)) : eventual upper bound
f(n) ∈ Ω(g(n)) : eventual lower bound
f(n) ∈ Θ(g(n)) : both; tight bound
f(n) ∈ o(g(n)) : strictly slower growth
Õ(g(n)) : hides logarithmic factors

Selection cue

If asked for “worst-case”, report an upper bound, preferably tight. If asked for “running time complexity” and you can prove both sides, use Θ. Big-O is a set, not an equals sign.

Origins: n is the input measure chosen in the question; c,n₀ are witnesses in the definition, not data values.

11010²10³10⁴10⁵124816input size n (log₂-spaced ticks)operations (log₁₀ scale)log₂nnn log₂n2ⁿ
Exact sample values at n∈{1,2,4,8,16}. Both axes use labeled logarithmic spacing so logarithmic, polynomial, and exponential work remain visible together.

Worked: binary search

Each comparison keeps only half the interval: after t iterations, remaining size is n/2ᵗ. Stop when n/2ᵗ ≤ 1, so t ≥ log₂n. Thus time is Θ(log n).

Iterative binary search stores only indices: Θ(1) auxiliary space. Recursive binary search has depth Θ(log n), so Θ(log n) call-stack space.

Check: doubling n adds one iteration.

Worked: nested loops are not automatically n²

for i in range(n):
    j = 1
    while j <= i:
        j *= 2

For fixed i, the inner loop runs ⌊log₂i⌋+1 times. Sum: Σᵢ log i = log(n!) = Θ(n log n). State the varying bound; do not multiply two “n loops” mechanically.

Growth order to know

1 ≺ log log n ≺ log n ≺ √n ≺ n ≺ n log n ≺ n² ≺ n³ ≺ cⁿ ≺ n! for constant c>1. Log bases differ only by a constant, so they are identical in Θ-notation.

🟠 Exam-practical Pseudo-polynomial: a running time polynomial in a numeric value but exponential in its bit-length. Example: looping to value W is O(W), but the input stores W in only Θ(log W) bits.

⚔ From the real exams — drill it

The search-complexity ladder opened the most recent exam. Same ladder, new story, every year.

2025 SUMMER · P1(a) · 2 PTS🔴 Exam-core
Exam 2025 Summer Problem 1(a): data stream of username/post pairs, set S of 1 billion allowed usernames, unsorted — worst-case complexity of a naive lookup
Exam 2025 Summer.pdf · Problem 1(a)
✍ Exam answer — short and enough

O(n) — unsorted, so worst case checks every element of S once (linear scan; here n = 10⁹).

Why that earns the marks

Two things are being graded: the bound and the one-line reason. “Unsorted ⇒ nothing rules out any element ⇒ must compare against each in the worst case.” Name n (|S|). Don't write more — 2 points, two sentences maximum.

→ A4 sheet: naive lookup unsorted: O(n) — one line in your search ladder (below).
2025 SUMMER · P1(c) · 4 PTS🔴 Exam-core
Exam 2025 Summer Problem 1(c): worst-case complexity of binary search, balanced search trees, and hash tables (expected and worst)
Exam 2025 Summer.pdf · Problem 1(c)
✍ Exam answer

Binary search: O(log n) — halves the range each step.
Balanced search tree: O(log n) — height kept logarithmic.
Hash table: expected O(1), worst O(n) — all keys can collide into one bucket.

Why that earns the marks

Each bound + its 4-to-8-word reason. The hash-table line is the trap: the question explicitly asks for both expected and worst case — leaving out O(n) costs the point. If asked what makes the expected case hold: a good hash function spreads keys uniformly, load factor kept constant by resizing.

→ A4 sheet: the search ladder block: lookup: naive O(n) · binary O(log n) (sorted!) · balanced BST O(log n) · hash exp O(1)/worst O(n) · Bloom O(k)=O(1), FP possible, no FN
2025 SUMMER · P1(d) · 2 PTS🟠 Exam-practical
Exam 2025 Summer Problem 1(d): what happens to binary search, balanced trees and hash tables if S does not fit in RAM
Exam 2025 Summer.pdf · Problem 1(d)
✍ Exam answer

The structures spill to disk → every probe can become a disk access, orders of magnitude slower (swapping/paging). Asymptotics unchanged, real time dominated by I/O. Practical fix: disk-aware structures (e.g. B-trees) or a small in-RAM prefilter (Bloom filter, next part).

Why that earns the marks

The examiner wants you to separate the model (O-notation counts comparisons) from the machine (a random disk access costs ~10⁵× a RAM access). Naming either B-trees or the Bloom filter as mitigation shows you see where the problem is heading — (e) asks for the Bloom filter explicitly.

→ A4 sheet: no RAM: disk I/O dominates → B-tree / Bloom prefilter
Chapter 2

Recursion, recurrences and dynamic programming

🔴 Exam-core A recurrence models total work by separating recursive calls from non-recursive work. Always define the base case and what n measures.

Master theorem — a decision procedure

T(n) = aT(n/b) + f(n), a ≥ 1, b > 1
critical term = n^(log_b a)
  1. Read a = number of equal-size calls, b = shrink factor, and f(n) = combine/non-recursive work.
  2. Compute c=log_ba=ln(a)/ln(b).
  3. Compare f(n) with nᶜ. Polynomially smaller → Case 1, same up to log factors → Case 2, polynomially larger plus regularity → Case 3.
CaseConditionConclusion
1f(n)=O(n^(c−ε))T(n)=Θ(nᶜ)
2f(n)=Θ(nᶜ logᵏn), k≥0T(n)=Θ(nᶜ log^(k+1)n)
3f(n)=Ω(n^(c+ε)) and af(n/b)≤qf(n), q<1T(n)=Θ(f(n))

Assumptions: subproblems have the same fraction n/b; floors/ceilings do not change the asymptotic answer; f is eventually positive. If sizes differ, use Akra–Bazzi.

Case 1

T(n)=8T(n/2)+n². Here c=log₂8=3; n²=O(n^(3−1)). Therefore T(n)=Θ(n³).

The leaves dominate.

Case 2

T(n)=2T(n/2)+n. Here c=1, f(n)=Θ(nᶜ), k=0. Therefore T(n)=Θ(n log n).

Every tree level costs n; there are log₂n levels.

Case 3

T(n)=2T(n/2)+n². c=1; n²=Ω(n^(1+1)). Regularity: 2(n/2)²=n²/2. Thus Θ(n²).

The root dominates.

cost nn/2n/2n/4n/4n/4n/4Each level totals n · depth log₂n → Θ(n log n)
Merge-sort recurrence tree; node widths are symbolic, but the level totals and depth correspond to the worked recurrence.

Substitution: a recurrence the revision slide mishandles

For T(n)=4T(n−1)+1, expand powers carefully:

T(n)=4[4T(n−2)+1]+1 = 4²T(n−2)+4+1
=4ᵏT(n−k)+(4ᵏ−1)/3

Set k=n−1 to hit T(1). Hence T(n)=Θ(4ⁿ). The source expansion drops exponents; this is a recorded correction, not a new theorem.

Revision Part 1, p. 6.COURSE CORRECTED

Top-down DP

Write the recursive definition first; cache by the full state. Each distinct state is solved once.

def fib(n, memo={}):
    if n < 2: return n
    if n not in memo:
        memo[n] = fib(n-1,memo)+fib(n-2,memo)
    return memo[n]

Θ(n) time, Θ(n) cache plus stack.

Bottom-up DP

Order states so every dependency already exists.

def fib(n):
    if n < 2: return n
    a, b = 0, 1
    for _ in range(2, n+1):
        a, b = b, a+b
    return b

Θ(n) time, Θ(1) auxiliary space.

⚔ From the real exams — drill it

The “Deggendorf numbers” block is the professor's favorite recursion vehicle — it has appeared, with the same definition, in at least four exams. Learn the five-part chain once and it is 25 nearly-free points.

2024–25 RESIT · P1(a) · 4 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 1(a): Deggendorf numbers deg(n)=1 for n in {0,1,2}, else deg(n-1)+deg(n-2)+deg(n-3) — provide a naive implementation
Exam 2024-25 Winter Resit.pdf · Problem 1(a)
✍ Exam answer
def deg(n):
    if n < 3:
        return 1
    return deg(n-1) + deg(n-2) + deg(n-3)
Why that earns the marks

“Naive” means: translate the mathematical definition literally, base case first. n < 3 covers exactly n ∈ {0, 1, 2}. Nothing else is wanted here — memoization comes later in the problem, and writing it now answers the wrong subpart.

→ A4 sheet: nothing — you can always transcribe the given definition. Save the space.
2024–25 RESIT · P1(b) · 5 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 1(b): derive the worst-case running time complexity of the naive implementation
Exam 2024-25 Winter Resit.pdf · Problem 1(b)
✍ Exam answer

Each call makes 3 recursive calls; the recursion tree has depth ≈ n.
T(n) = T(n−1) + T(n−2) + T(n−3) + O(1) ≤ 3T(n−1) + O(1)
→ tree of ≤ 3n nodes, O(1) work each.

T(n) = O(3n) — exponential.
Why that earns the marks

“Derive” = show the recurrence and the tree argument, not just say “exponential”. The three-line chain (recurrence → bound by the 3-ary tree → node count × constant work) is exactly the supported reasoning the cover sheet demands. The true growth rate is the tribonacci constant ≈ 1.84ⁿ; O(3ⁿ) as an upper bound with the tree argument is the expected full-marks answer.

→ A4 sheet: 3-branch recursion → T ≤ 3T(n−1)+O(1) → O(3^n); k-branch → O(k^n)
2024–25 RESIT · P1(c) · 4 PTS🟠 Exam-practical
Exam 2024-25 Resit Problem 1(c): visualize the complete recursion tree for deg(4)
Exam 2024-25 Winter Resit.pdf · Problem 1(c)
✍ Exam answer — draw this
deg(4)
├─ deg(3)
│  ├─ deg(2)=1
│  ├─ deg(1)=1
│  └─ deg(0)=1
├─ deg(2)=1
└─ deg(1)=1        result: deg(4) = 3+1+1 = 5
Why that earns the marks

“Complete” means every call node, including the three base-case leaves under deg(3). Adding the returned values (deg(3)=3, so deg(4)=5) is the free sanity check that shows the tree is right. Note deg(2) appears twice — that duplicated subtree is precisely the argument for part (d)'s memoization.

→ A4 sheet: deg: 1,1,1,3,5,9,17… (values from n=0 — lets you verify any tree instantly)
2024–25 RESIT · P1(d) · 8 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 1(d): re-implement using top-down dynamic programming without Python auxiliary tools
Exam 2024-25 Winter Resit.pdf · Problem 1(d)
✍ Exam answer
def deg(n, memo=None):
    if memo is None:
        memo = {}
    if n < 3:
        return 1
    if n not in memo:
        memo[n] = deg(n-1, memo) + deg(n-2, memo) + deg(n-3, memo)
    return memo[n]

Each deg(i) computed once → O(n) time, O(n) space.

Why that earns the marks

Top-down = keep the recursive shape, add a cache. “Without auxiliary tools” bans lru_cache — a hand-rolled dict is exactly what's wanted. The memo=None default avoids Python's mutable-default-argument trap (a shared dict across calls) — mentioning that shows real understanding. Always end a DP answer with the new complexity: that's where the 8 points close.

Bottom-up variant (asked in 2020–21): a=b=c=1, loop for _ in range(3, n+1): a, b, c = b, c, a+b+c, return c — O(n) time, O(1) space.

→ A4 sheet: the memo skeleton, 4 lines: def f(n, memo=None): if memo is None: memo={} · if base: return … · if n not in memo: memo[n]=… · return memo[n] + bottom-up: rolling vars, O(1) space
2024–25 RESIT · P1(e) · 4 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 1(e): how does Python support memoizing function calls — explain and re-implement using that tool
Exam 2024-25 Winter Resit.pdf · Problem 1(e)
✍ Exam answer

functools.lru_cache — a decorator that caches results keyed by the call arguments; repeated calls return the cached value.

from functools import lru_cache

@lru_cache(maxsize=None)
def deg(n):
    if n < 3:
        return 1
    return deg(n-1) + deg(n-2) + deg(n-3)
Why that earns the marks

Name the tool, one sentence on what it does, then the naive code with the decorator on top — that is the whole answer. (Your old handwritten sheet had exactly this import line at the top. It stays.)

→ A4 sheet: from functools import lru_cache · @lru_cache(maxsize=None)
2023–24 RESIT · P1(a)+(b) · 10 PTS🟠 Exam-practical
Exam 2023-24 Resit Problem 1(a): convert the recursive binary search implementation into an iterative oneExam 2023-24 Resit Problem 1(b): space complexity of both binary search variants with explanations
Exam 2023-24 Winter Resit.pdf · Problem 1(a)–(b)
✍ Exam answer
def binary_search(data, target):
    low, high = 0, len(data) - 1
    while low <= high:
        mid = (low + high) // 2
        if data[mid] == target:
            return True
        elif data[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return False

(b) Recursive: O(log n) auxiliary space — one stack frame per halving.
Iterative: O(1) — three variables, no growing state.

Why that earns the marks

This is your handwritten sheet's binary-search block, verbatim — it survives to the new sheet. The space question is the actual test: recursion isn't free, each nested call holds a frame until it returns, and binary search nests Θ(log n) deep. The iterative rewrite eliminates exactly that. Say “auxiliary space” — the input itself doesn't count.

→ A4 sheet: keep your iterative binary-search block + space: recursive O(log n) stack, iterative O(1)
2024 SUMMER · P2(d)+(e) · 16 PTS🔴 Exam-core
Exam 2024 Summer Problem 2(d): implement the sign function returning -1, 0 or 1Exam 2024 Summer Problem 2(e): implement bisection(f, a, b, tol, max_iterations) root finding with hints about sign checks and tolerance
Exam 2024 Summer.pdf · Problem 2(d)–(e) — 13-point implementation, the largest single code task in recent exams
✍ Exam answer
def sign(x):
    if x < 0:
        return -1
    elif x == 0:
        return 0
    return 1

def bisection(f, a, b, tol, max_iterations):
    if sign(f(a)) == sign(f(b)):
        raise ValueError('f(a) and f(b) must differ in sign')
    for _ in range(max_iterations):
        m = (a + b) / 2
        if abs(f(m)) < tol:      # tolerance: |f(m)| < tol → converged
            return m
        if sign(f(m)) == sign(f(a)):
            a = m                # root is in right half
        else:
            b = m                # root is in left half
    return (a + b) / 2

Tolerance used as: stop when |f(m)| < tol (function value close enough to 0).

Why that earns the marks

Bisection is binary search on a continuous function: the invariant is sign(f(a)) ≠ sign(f(b)), so the interval always contains a root (intermediate value theorem — name it if asked for justification). The loop keeps the invariant by replacing the boundary whose sign matches the midpoint's. The hints in the question are a grading checklist: (1) they want the sign-preserving update shown, (2) they want your tolerance convention stated in words — either |f(m)| < tol or interval width (b−a)/2 < tol is accepted if you say which. The bound check at the top plus max_iterations as a fail-safe are the remaining marks.

→ A4 sheet: the 10-line bisection body (it recurs across exams) + invariant: sign(f(a))≠sign(f(b)); state tol convention!
2024 SUMMER · P1(a)+(b) · 9 PTS🟠 Exam-practical
Exam 2024 Summer Problem 1(a): implement min_max1 with a loop, no recursionExam 2024 Summer Problem 1(b): implement min_max2 with recursion, no loop — rethink the signature
Exam 2024 Summer.pdf · Problem 1(a)–(b)
✍ Exam answer
def min_max1(data):
    mn = mx = data[0]
    for v in data[1:]:
        if v < mn: mn = v
        if v > mx: mx = v
    return mn, mx

def min_max2(data, i=0):        # signature rethought: index parameter
    if i == len(data) - 1:
        return data[i], data[i]
    mn, mx = min_max2(data, i + 1)
    return min(data[i], mn), max(data[i], mx)
Why that earns the marks

“Rethink the signature” is the hint that pure min_max2(data) can't recurse cleanly — add an index (or slice, but slicing copies O(n) per level, worth a remark). Pattern: solve the rest recursively, combine with the current element. Both return a tuple — matching “returns both” in the statement.

→ A4 sheet: recursion pattern: base = last element · combine = min/max(current, rest)
Chapter 3

Sorting and deterministic selection

🔴 Exam-core Know the properties, trace one pass, and derive rather than memorize where possible. Selection asks for the k-th order statistic without fully sorting.

AlgorithmBestAverageWorstAux. spaceStable?In place?
Bubble (early stop)Θ(n)Θ(n²)Θ(n²)Θ(1)YesYes
InsertionΘ(n)Θ(n²)Θ(n²)Θ(1)YesYes
MergeΘ(n log n)Θ(n log n)Θ(n log n)Θ(n)Yes*No*
QuicksortΘ(n log n)Θ(n log n)Θ(n²)Θ(log n) avg stackNoUsually
HeapΘ(n log n)Θ(n log n)Θ(n log n)Θ(1)NoYes
BucketΘ(n+k)Θ(n+k) expected under a uniform-distribution assumptionΘ(n²)Θ(n+k)DependsNo

*For the standard course implementations. Source: Slides, pp. 339–382; Sorting tutorial, pp. 2–27.

Merge sort from its recurrence

Two half-size recursive sorts plus linear merging:

T(n)=2T(n/2)+Θ(n)

Master: a=2,b=2,c=1,f(n)=Θ(n); Case 2 gives Θ(n log n). Stability comes from choosing the left item first on equal keys.

Comparison sorting lower bound is Ω(n log n), so merge sort is asymptotically optimal in that model.

Quicksort: explain the bad pivot

If the pivot is always smallest/largest, partitions are sizes 0 and n−1:

T(n)=T(n−1)+Θ(n)=Θ(n²)

Random pivots make expected partitions sufficiently balanced, yielding expected Θ(n log n). This is expected, not guaranteed.

Stability in one sentence

A stable sort preserves the input order of records with equal keys. Test with decorated records: (2,A),(1,X),(2,B) must end as (1,X),(2,A),(2,B). Stability matters when sorting by multiple fields in stages.

Median of medians — complete source exercise

Question: find the 11th smallest in [31,8,22,4,17,29,13,2,26,11,15,6,19,1,24,7,28,10,20,3,27,9]; equivalently zero-based rank k=10.

  1. Groups of five: [31,8,22,4,17]→17, [29,13,2,26,11]→13, [15,6,19,1,24]→15, [7,28,10,20,3]→10, leftover [27,9]→9 using the source’s lower-median convention.
  2. Medians are [17,13,15,10,9]; their median is pivot 13.
  3. Partition original data: less has 10 values [8,4,2,11,6,1,7,10,3,9]; equal has 1; greater has 11.
  4. Because zero-based k=10 equals |less|, the equal partition contains the target. Answer: 13.

Independent check: sorted order begins 1,2,3,4,6,7,8,9,10,11,13,…, so the 11th value is 13.

Why median-of-medians is linear

Group into fives, recursively select the median of the group medians, partition, and recurse only on the side containing rank k. At least about 3n/10 elements are discarded (up to constants), so the worst recurrence is:

T(n) ≤ T(n/5)+T(7n/10)+cn = Θ(n)

Master theorem does not apply because subproblem sizes differ. Akra–Bazzi yields an exponent below 1 for the recursive part, while the linear partition integral makes the total Θ(n).

⚔ From the real exams — drill it

Every summer exam has a 25-point sorting problem, and the merge function has been asked, verbatim, at least three times.

2025 SUMMER · P2(a) · 7 PTS🔴 Exam-core
Exam 2025 Summer Problem 2(a): complete the merge(S1, S2, S) function that merges two sorted lists, with visualization
Exam 2025 Summer.pdf · Problem 2(a)
✍ Exam answer
def merge(S1, S2, S):
    i = j = 0
    while i + j < len(S):
        if j == len(S2) or (i < len(S1) and S1[i] < S2[j]):
            S[i+j] = S1[i]
            i += 1
        else:
            S[i+j] = S2[j]
            j += 1
Why that earns the marks

The one condition line carries the whole function: take from S1 when S2 is exhausted (j == len(S2)) or S1's front element is smaller (guarded by i < len(S1) so we never overrun). i + j is both the write position and the loop bound — the invariant is “S[0 : i+j] holds the i+j smallest elements, merged”. This is the course's own implementation (it was on your handwritten sheet, with the same short-circuit trick) — reproduce it exactly; inventing a different merge risks losing the “as discussed in class” marks.

→ A4 sheet: the 8-line merge, verbatim. Highest code-reuse-per-cm² on the whole sheet.
2025 SUMMER · P2(b)+(c) · 13 PTS🔴 Exam-core
Exam 2025 Summer Problem 2(b): reimplement merge sort splitting into four sublists using the given merge_sort and mergeExam 2025 Summer Problem 2(c): derive the worst-case complexity of the 4-way variant and compare with the original
Exam 2025 Summer.pdf · Problem 2(b)–(c)
✍ Exam answer
def merge_sort4(S):
    n = len(S)
    if n < 2:
        return
    q, m, p = n//4, n//2, 3*n//4
    S1, S2, S3, S4 = S[:q], S[q:m], S[m:p], S[p:]
    merge_sort4(S1); merge_sort4(S2)
    merge_sort4(S3); merge_sort4(S4)
    T1, T2 = S1 + S2, S3 + S4     # right-sized containers
    merge(S1, S2, T1)
    merge(S3, S4, T2)
    merge(T1, T2, S)

(c) Recurrence: T(n) = 4T(n/4) + O(n).
Master theorem (applicable: a=4 ≥ 1, b=4 > 1, f(n)=O(n¹), d=1): log₄4 = 1 = d → case 2.

T(n) = O(n log n) — same as 2-way merge sort.
Why that earns the marks

(b): split into four quarters, sort each recursively, then merge pairwise — the statement says you may reuse two-list merge, so three merge calls (S1+S2, S3+S4, then the halves) is the intended shape. T1, T2 = S1+S2, S3+S4 just creates containers of the right length for merge to overwrite.

(c): the derivation must name the recurrence, then the theorem with the applicability check — the cover sheet's “fundamental theorem” rule. Per level all merges touch each element a constant number of times → O(n) per level; depth log₄n; log₄n = log₂n / 2 — a constant factor, so identical asymptotics. That sentence is (d)'s answer too: no asymptotic benefit (possibly fewer recursion levels, but more merge passes per level — constants shuffle, Θ(n log n) stays).

→ A4 sheet: k-way merge sort: T(n)=kT(n/k)+O(n) → O(n log n) ∀k — log base = constant factor
2025 SUMMER · P2(e) · 3 PTS🔴 Exam-core
Exam 2025 Summer Problem 2(e): lower bound of comparison-based sorting; can we sort better than that bound?
Exam 2025 Summer.pdf · Problem 2(e)
✍ Exam answer

Lower bound: Ω(n log n) comparisons — a comparison sort must distinguish n! orderings; a decision tree of height h has ≤ 2h leaves, so h ≥ log₂(n!) = Θ(n log n).
Yes — non-comparison sorts beat it under assumptions: counting/bucket sort O(n+k), radix O(d·n) for bounded integer keys.

Why that earns the marks

Both halves are required: the bound with the decision-tree sentence, and the escape hatch (“yes, if we don't only compare”). Naming one non-comparison sort with its complexity and its assumption (keys from a bounded/integer universe) completes it.

→ A4 sheet: comparison sort ≥ log₂(n!) = Ω(n log n); counting/bucket O(n+k), radix O(dn) — need bounded keys
2024 SUMMER · P3(a)+(b) · 8 PTS  ·  ALSO 2022 · P2🔴 Exam-core
Exam 2024 Summer Problem 3(a): name three stable sorting algorithmsExam 2024 Summer Problem 3(b): explain stability with an example
Exam 2024 Summer.pdf · Problem 3(a)–(b)
✍ Exam answer

(a) Stable: bubble, insertion, merge. (Not stable: selection, quicksort, heapsort.)
(b) Stable = equal keys keep their input order. Example: sorting [(2,'a'), (1,'x'), (2,'b')] by number → stable gives (2,'a') before (2,'b'); an unstable sort may swap them. Matters when sorting by a second key after a first.

Why that earns the marks

“Names only” questions are pure sheet lookups — this is why the sorting table belongs on your A4 side. For the explanation: definition in one sentence + a two-element tie example + one “why it matters” clause. Done in four lines.

→ A4 sheet: the full sorting table (below, in the A4 synthesis): name · best · avg · worst · space · stable? · in-place?
2024 SUMMER · P3(e)+(f) · 7 PTS🟠 Exam-practical
Exam 2024 Summer Problem 3(e): the class bubble sort implementationExam 2024 Summer Problem 3(f): re-implement bubble sort so its best-case complexity improves; state the new best case
Exam 2024 Summer.pdf · Problem 3(e)–(f)
✍ Exam answer
def bubble_sort(data):
    n = len(data)
    for i in range(n - 1):
        swapped = False
        for j in range(n - 1 - i):
            if data[j] > data[j+1]:
                data[j], data[j+1] = data[j+1], data[j]
                swapped = True
        if not swapped:
            return            # already sorted — stop

Best case (already sorted): one pass, no swaps → O(n); worst stays O(n²).

Why that earns the marks

The swapped flag is the entire trick: a pass with zero swaps proves sortedness, so bail out. State both the new best case and that the worst case is unchanged — the comparison is what the subpart is really asking for.

→ A4 sheet: bubble + swapped flag → best O(n) (one line under the sorting table)
Chapter 4

Lists, stacks, queues, iterators and generators

🔴 Exam-core The latest exam makes this a full problem. Pointer diagrams are executable specifications: draw the nodes, identify the predecessor, change links in a safe order, then update size.

Array list

  • Θ(1) indexing.
  • Append is amortized Θ(1); an individual resize is Θ(n).
  • Middle insert/delete is Θ(n) due to shifting.
  • Compact memory and cache-friendly traversal.

Linked list

  • Θ(n) access by index.
  • Θ(1) insert/delete given the relevant node/predecessor.
  • No contiguous reallocation; nodes can grow one at a time.
  • Pointer overhead and weaker locality.
prevold nextnew node1 · new.next = prev.next 2 · prev.next = newold link (replaced)
Original pointer trace. Both outgoing targets are preserved; overwriting prev.next first would lose the remainder unless it was saved.

Latest exam Problem 1 — full code and reasoning

class LinkedList:
    class Node:
        def __init__(self, element):
            self.element = element
            self.next_element = None

    def __init__(self):
        self.head = None
        self.size = 0

    # (a)
    def add_middle(self, element):
        # Odd length has no single gap at the middle: leave unchanged.
        if self.size % 2 == 1:
            return False
        new = self.Node(element)
        if self.size == 0:
            self.head = new
        else:
            prev = self.head
            for _ in range(self.size // 2 - 1):
                prev = prev.next_element
            new.next_element = prev.next_element
            prev.next_element = new
        self.size += 1
        return True

    # (b)
    def remove_first(self):
        if self.head is not None:
            self.head = self.head.next_element
            self.size -= 1

    # (d)
    def __iter__(self):
        current = self.head
        while current is not None:
            yield current.element
            current = current.next_element

(a) Why middle is correct: for even size 2r, the new node is inserted after the first r nodes. The loop stops on index r−1. Empty list is even and inserts at the head. An odd list returns False with no mutation.

(c) Two benefits each: linked lists support Θ(1) insertion/deletion when the predecessor is known and grow without contiguous reallocation; array lists provide Θ(1) indexing and compact, cache-friendly storage.

Complexities for (a), (b), and (d): add_middle Θ(n) time/Θ(1) extra space; remove_first Θ(1); iteration Θ(n) total and Θ(1) generator state.

Trace tests: []→[x]; odd [x] unchanged; [a,b]→[a,x,b]; remove until empty; iteration yields every value once. A generator is lazy: each yield suspends state until the next request.

ADT transfer cues

Stack: LIFO; push/pop/top at one end, all Θ(1). Queue: FIFO; enqueue rear/dequeue front Θ(1) with a deque or linked endpoints. Deque: both ends. If an array queue shifts elements on every dequeue, it is accidentally Θ(n); use a circular buffer/head index.

⚔ From the real exams — drill it

The most recent resit spent a full 25-point problem on linked-list surgery; MyArray methods recur across exams. Pointer updates and size bookkeeping are where the marks leak.

2025–26 RESIT · P1(a) · 9 PTS🔴 Exam-core
Exam 2025-26 Resit Problem 1(a): implement add_middle for the course LinkedList class — only possible for even element counts; handle odd correctly
Exam 2025-26 Winter Resit.pdf · Problem 1(a) — includes the course's LinkedList/_Node class
✍ Exam answer
def add_middle(self, element):
    if self._size % 2 != 0:
        raise ValueError('only possible for even number of elements')
    node = self._Node(element)
    if self._size == 0:
        self._head = node
    else:
        cur = self._head
        for _ in range(self._size // 2 - 1):
            cur = cur._next_element
        node._next_element = cur._next_element
        cur._next_element = node
    self._size += 1
Why that earns the marks

Grading checklist for any list-mutation method: (1) the odd case — the statement explicitly demands “handle it correctly”, and raising a clear error is correct handling; (2) the empty list (size 0 is even — the new node becomes the head); (3) walk exactly size/2 − 1 hops so cur is the node before the middle; (4) link the new node before re-pointing cur — the classic order mistake loses the tail; (5) update _size. Five checkpoints ≈ 9 points.

→ A4 sheet: list insert after cur: node.next = cur.next; cur.next = node (this order!) · always ±size · walk k hops → node k+1
2025–26 RESIT · P1(b)+(c) · 9 PTS🔴 Exam-core
Exam 2025-26 Resit Problem 1(b): implement remove_first returning nothingExam 2025-26 Resit Problem 1(c): name two benefits of linked lists and of array lists respectively
Exam 2025-26 Winter Resit.pdf · Problem 1(b)–(c)
✍ Exam answer
def remove_first(self):
    if self._head is None:
        return
    self._head = self._head._next_element
    self._size -= 1

(c) Linked list: O(1) insert/remove at head; grows without resizing (no capacity waste).
Array list: O(1) random access by index; contiguous memory → cache-friendly.

Why that earns the marks

(b) is four lines, but two of them are the graded ones: the empty-list guard and the size decrement. The removed node needs no explicit freeing — Python's GC collects it once unreferenced (say this if asked). (c) wants two benefits each — symmetric answers; complexity-flavored phrasing (O(1) head ops vs O(1) indexing) is the safest currency.

→ A4 sheet: linked: O(1) head ins/del, no resize · array: O(1) index, cache-local; append O(1) amortized
2025–26 RESIT · P1(d) · 7 PTS🔴 Exam-core
Exam 2025-26 Resit Problem 1(d): implement a generator so a linked list can be iterated with a for loop
Exam 2025-26 Winter Resit.pdf · Problem 1(d)
✍ Exam answer
def __iter__(self):
    cur = self._head
    while cur is not None:
        yield cur._element
        cur = cur._next_element
Why that earns the marks

The usage snippet (for value in lst:) tells you the method name: Python's for-loop protocol calls __iter__. Any function containing yield is a generator — Python builds the iterator object for you, state (the paused position) included. Yield the element, not the node. This same 5-liner answered the 2023 Summer exam too — it recycles.

→ A4 sheet: the 5-line __iter__ generator, verbatim.
2025 SUMMER · P3(d) · 5 PTS  ·  setitem variant 2023–24🔴 Exam-core
Exam 2025 Summer Problem 3(d): implement MyArray.insert(k, value) handling negative indices, given the ctypes-based MyArray class
Exam 2025 Summer.pdf · Problem 3(d) — the course's ctypes MyArray class
✍ Exam answer
def insert(self, k, value):
    if k < 0:
        k += self._n              # negative index → from the end
    k = max(0, min(k, self._n))   # clamp like list.insert
    if self._n == self._capacity:
        self._resize(2 * self._capacity)
    for i in range(self._n, k, -1):
        self._A[i] = self._A[i-1] # shift right, back to front
    self._A[k] = value
    self._n += 1
Why that earns the marks

Four graded moves: normalize the negative index (k += n — the explicit requirement); grow when full (doubling, matching the class design — this is why append is O(1) amortized); shift from the back so nothing is overwritten; write + increment size. If the variant asks for __setitem__ instead (2023–24 resit): same negative-index normalization, then bounds-check and assign — no shifting.

→ A4 sheet: MyArray: neg idx → k+=n · full → _resize(2·cap) · shift n→k backwards · doubling ⇒ append O(1) amortized
Chapter 5

Graphs and shortest paths

🟠 Exam-practical Representations and “frontier” meaning recur in exams. Dijkstra is the lowest-cost algorithm for non-negative edge weights; BFS is shortest path only in unweighted/equal-weight graphs.

Adjacency list

Space Θ(|V|+|E|). Iterating neighbors of v costs Θ(deg(v)). Best for sparse graphs.

Adjacency matrix

Space Θ(|V|²). Edge query is Θ(1); scanning all neighbors is Θ(|V|). Symmetric for undirected graphs.

31253A · 0B · 3C · 1D · 4Settled order A → C → B → D; shortest A→D is A–C–D, cost 4

Dijkstra by hand

Maintain tentative distance d[v] and predecessor. Initialize d[A]=0, all others . Repeatedly settle the unvisited vertex with minimum tentative distance and relax each outgoing edge:

if d[u]+w(u,v) < d[v]: d[v]←d[u]+w(u,v), pred[v]←u
Settled(A)d(B)d(C)d(D)Change
start0
A031B←A, C←A
C0314D←C; B candidate 3 ties
B0314D candidate 8, no
D0314done

Output: distances A=0,B=3,C=1,D=4; path to D by predecessors is A→C→D. With binary heap and adjacency lists: O((|V|+|E|)log|V|), often written O(|E|log|V|) for connected sparse graphs.

Assumption check: all edge weights are non-negative. Negative edges invalidate the settle-once proof.

Frontier

The frontier is the collection of discovered but not yet expanded states, plus the operation used to choose the next one. Queue → BFS; stack → DFS; min-priority queue by path cost → Dijkstra; by g+h → A*. The choice changes the search order and guarantees.

⚔ From the real exams — drill it

The graph opener (formal definition + adjacency matrix) and the frontier/deque argument together appear in over half of all past exams.

2025 SUMMER · P3(a) · 7 PTS🔴 Exam-core
Exam 2025 Summer Problem 3(a): formal k-tuple definition and adjacency matrix of a weighted directed 4-node graph
Exam 2025 Summer.pdf · Problem 3(a)
✍ Exam answer

Directed + weighted → 3-tuple G = (V, E, w):

V = {1,2,3,4}
E = {(1,2), (2,1), (2,3), (3,4), (4,3)}
w(1,2)=3, w(2,1)=2, w(2,3)=4, w(3,4)=1, w(4,3)=2

A =        to: 1  2  3  4      (row = from, entry = weight, 0 = no edge)
  from 1  [   0  3  0  0 ]
  from 2  [   2  0  4  0 ]
  from 3  [   0  0  0  1 ]
  from 4  [   0  0  2  0 ]
Why that earns the marks

“k-tuple” is a prompt to count what the graph has: nodes and edges always (V, E); weights add w: E→ℝ; the graph is directed, so E contains ordered pairs and A need not be symmetric (here it isn't: A[1][2]=3 but A[2][1]=2 — different arcs). Read each arrowhead carefully: the two arcs of a node pair are separate directed edges with separate weights. State your row-convention (“row = from”) — either convention is accepted if declared.

→ A4 sheet: G=(V,E) · +weights: (V,E,w), w:E→ℝ · digraph: ordered pairs, A asym · row=from (declare!) · space: matrix O(V²), adj list O(V+E)
2025 SUMMER · P3(b)+(c) · 8 PTS  ·  ALSO 2021 · 2020–21 · 2023–24🔴 Exam-core
Exam 2025 Summer Problem 3(b): why does frontier being a Python list make shortest_path_search unnecessarily slow — argue with O and Theta; the full shortest_path_search implementation is givenExam 2025 Summer Problem 3(c): provide a more efficient implementation using the different data structure, rewriting only a few lines
Exam 2025 Summer.pdf · Problem 3(b)–(c)
✍ Exam answer

(b) Line 09 frontier.pop(0) on a Python list is Θ(n) — every remaining element shifts left one slot. Done once per expanded path → up to Θ(n²) total shifting. The frontier is used FIFO (append at back, take from front) → the right ADT is a queue, e.g. collections.deque: popleft() and append() are O(1).

(c) Rewrite two lines:

07: frontier = deque([ [start] ])
09: path = frontier.popleft()
Why that earns the marks

The question names its own rubric: use O and Θ. Θ(n) for pop(0) is the precise claim (it always shifts, not just in the worst case); O(1) for the deque ops. Then say why a queue is the right ADT: breadth-first order = first discovered, first expanded. In (c), reference the line numbers explicitly (“rewriting lines 07 and 09”) — the statement demands it — and change nothing else; append on line 18 already works on a deque.

→ A4 sheet: list.pop(0) Θ(n) → deque.popleft() O(1) · frontier = discovered, not yet expanded · BFS queue / DFS stack / Dijkstra min-heap
Chapter 6

Trees, traversal and ID3 decision learning

🔴 Exam-core ID3 is the strongest explicit hint. Treat it as an accounting problem: parent entropy minus the weighted entropy remaining after a split.

Traversal

Preorder: node, children. Inorder (binary): left, node, right. Postorder: children, node. Level order: BFS queue. A complete traversal is Θ(n); recursive auxiliary space is Θ(h), which is Θ(log n) when balanced and Θ(n) when degenerate.

Balanced search trees

Balance keeps height h=Θ(log n), making search/insert/delete Θ(log n). An unbalanced BST can become a chain with h=n−1 and Θ(n) operations.

Entropy and information gain

H(Y)=−Σᵢ pᵢ log₂pᵢ (define 0·log₂0 = 0)
Remainder(A)=Σᵥ |Sᵥ|/|S| · H(Y in Sᵥ)
IG(Y,A)=H(Y)−Remainder(A)

Meaning: entropy is label uncertainty in bits; remainder is expected uncertainty after learning attribute A; gain is uncertainty removed. pᵢ comes from label counts; Sᵥ is the subset with attribute value v. There are no physical units.

Cue/order: when asked to “learn a tree with ID3”, (1) count labels, (2) compute parent H, (3) for every candidate attribute make a branch count table, (4) compute weighted remainder and gain, (5) choose maximum gain, (6) recurse on impure branches. State how ties are broken.

Latest exam Problem 2(a) — every intermediate step

Labels: 2 positive, 4 negative. Parent entropy:

H(S)=−(2/6)log₂(2/6)−(4/6)log₂(4/6)=0.918296
AttributeBranch label counts (+,−)Weighted remainderGain
skycloudy (0,1), sunny (2,1), rainy (0,2)(1/6)0+(3/6)H(2/3,1/3)+(2/6)0 = 0.4591480.459148
airwarm (2,3), cold (0,1)(5/6)H(2/5,3/5)=0.8091250.109170
humidnormal (0,2), high (2,2)(2/6)0+(4/6)1=0.6666670.251629
windstrong (2,2), weak (0,2)(4/6)1+(2/6)0=0.6666670.251629

Root: sky has maximum gain. cloudy→−, rainy→−. For sunny rows, labels are +,+,−. Air is constant; humid and wind each separate perfectly: humid=high→+, humid=normal→−, or equivalently wind=strong→+, wind=weak→−. State a deterministic tie rule; choose humid.

sky?humid?+cloudysunnyrainyhighnormal
Tree exactly matches all six training rows. The sunny-branch humid/wind tie is explicit rather than silently arbitrary.

Exam-ready ending: “Choose sky because IG=0.4591 is maximal. Recurse only on sunny. Humid and wind tie with perfect gain; using humid as the stated tie-break gives the shown tree.”

⚔ From the real exams — drill it

ID3 is the single most reliable block of points in this course — a manual entropy/gain calculation appears in nearly every exam, worth 5–18 points. Two real instances below, both fully worked and machine-verified.

2024–25 RESIT · P3(a)+(b) · 10 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 3(a): mark the symmetric trees in the figure — trees are symmetric if equal to their inverseExam 2024-25 Resit Problem 3(b): implement is_symmetric using the TreeNode class with left/right children
Exam 2024-25 Winter Resit.pdf · Problem 3(a)–(b)
✍ Exam answer
def is_symmetric(node):
    def mirror(left, right):
        if left is None and right is None:
            return True
        if left is None or right is None:
            return False
        return (mirror(left.left, right.right) and
                mirror(left.right, right.left))
    if node is None:
        return True
    return mirror(node.left, node.right)
Why that earns the marks

Symmetry is a statement about two subtrees mirroring each other, so the recursion needs a two-argument helper: outer-vs-outer (left.left vs right.right) and inner-vs-inner. The two base cases carry points: both empty → symmetric; exactly one empty → not. This is verbatim from your old handwritten sheet — it was right then and it answered a real exam since. For the marking subpart (a): a tree is symmetric iff this mirror test passes; single-child nodes break symmetry unless mirrored on the other side.

→ A4 sheet: the mirror(l,r) helper — 3 lines of logic: both None→T · one None→F · mirror(l.l,r.r) and mirror(l.r,r.l)
2024 SUMMER · P1(d) · 7 PTS🔴 Exam-core
Exam 2024 Summer Problem 1(d): implement Node.sum returning the sum of all node values of a binary tree
Exam 2024 Summer.pdf · Problem 1(d)
✍ Exam answer
def sum(self):
    result = self.data
    if self.left is not None:
        result += self.left.sum()
    if self.right is not None:
        result += self.right.sum()
    return result
Why that earns the marks

The universal tree-recursion template: my value + recurse into whichever children exist. The is not None guards are the graded detail — calling None.sum() crashes. O(n) time (each node once), O(h) stack. The same skeleton answers count, height (1 + max(...)), find-max — one template, many exam questions. (Also on your old sheet — kept.)

→ A4 sheet: tree recursion: val = self.data (+ left.f() if left) (+ right.f() if right) — guard None!
2025 SUMMER · P3(e) · 5 PTS · ROOT ONLY🔴 Exam-core
Exam 2025 Summer Problem 3(e): use ID3 to find the root for the attack label on a 6-row dataset with attributes sky, air, humid, wind
Exam 2025 Summer.pdf · Problem 3(e)
✍ Exam answer (root only — ≈6 min with calculator)

Labels: 4+, 2− → H(S) = −(4/6)log₂(4/6) − (2/6)log₂(2/6) = 0.918

Gain(S,a) = H(S) − Σ_v (|S_v|/|S|)·H(S_v)

sky:   sunny(3+,1−) rainy(1+,1−) → rem = (4/6)·0.811+(2/6)·1 = 0.874 → G=0.044
air:   warm(4+,1−)  cold(0,1−)   → rem = (5/6)·0.722+(1/6)·0  = 0.601 → G=0.317
humid: normal(1+,1−) high(3+,1−) → rem = (2/6)·1+(4/6)·0.811  = 0.874 → G=0.044
wind:  strong(4+,1−) weak(0,1−)  → rem = (5/6)·0.722+(1/6)·0  = 0.601 → G=0.317
air and wind tie at Gain = 0.317 (max) → root = air (or wind — state the tie, pick one).
Why that earns the marks

“Write out intermediate steps” = the rubric: H(S), then per attribute the split counts, the weighted remainder, the gain. The layout above (one line per attribute) is the fastest complete form. This instance contains a deliberate tie — air and wind produce identical splits ((4+,1−)/(0,1−)); saying “tie — either is a valid root” is the mark-winning observation, silently picking one without comment is not. Calculator: log₂x = ln x ÷ ln 2; store H-values you reuse (0.811 = H(3,1), 0.722 = H(4,1), 1 = H(1,1)) — they recur constantly.

→ A4 sheet: H(S)=−Σp·log₂p · Gain = H − Σ(|Sv|/|S|)H(Sv) · log₂x = ln x/ln 2 + the mini-table H(1,1)=1 · H(3,1)=.811 · H(4,1)=.722 · H(4,2)=.918 · H(5,1)=.650
2025–26 RESIT · P2(a) · 11 PTS · FULL TREE🔴 Exam-core
Exam 2025-26 Resit Problem 2(a): learn a full ID3 tree for the attack label on a 6-row dataset — cloudy/sunny/rainy sky, air, humid, wind
Exam 2025-26 Winter Resit.pdf · Problem 2(a)
✍ Exam answer (full tree — ≈12 min)

Labels: 2+, 4− → H(S) = 0.918.

sky:   cloudy(0,1−) sunny(2+,1−) rainy(0,2−)
       rem = (1/6)·0 + (3/6)·0.918 + (2/6)·0 = 0.459 → G = 0.459  ← max
air:   G = 0.109   humid: G = 0.252   wind: G = 0.252

Root = sky. Branches: cloudy → all −, leaf “−”; rainy → all −, leaf “−”.
sunny = {2:+, 4:+, 5:−}, H = 0.918. Within sunny:

humid: high(2+,0) normal(0,1−) → rem 0 → G = 0.918  ← max (wind ties)
air, sky: G = 0 (all warm/sunny)
Tree: sky — cloudy→−, rainy→−, sunny→humid (high→+, normal→−). (wind is an equally valid second split — tie)
Why that earns the marks

“Full tree” = repeat the root procedure inside every impure branch. The efficient exam order: (1) root gains, (2) close the pure branches immediately (cloudy, rainy are all-negative — no calculation needed, say “pure → leaf”), (3) recurse only into sunny with its 3 rows. Attributes with one value in the subset (air = all warm) have gain 0 — one clause, no arithmetic. Again a tie (humid/wind) — state it. Verify at the end: run each training row down the tree; all 6 must classify correctly.

→ A4 sheet: the ID3 procedure, 4 steps: 1. H(S) 2. per attr: split counts → weighted rem → gain 3. max gain = node, pure branch = leaf 4. recurse per branch on remaining attrs
Chapter 7

Maps, hashing and Bloom filters

🔴 Exam-core A map binds keys to values. Hash tables aim for expected Θ(1) lookup; Bloom filters answer approximate membership with no false negatives (under normal operation) and possible false positives.

Collision handling

Separate chaining: each bucket stores a collection. Expected operations are Θ(1+α), where load factor α=m/n. Worst case Θ(m).

Linear probing: on collision try h(k),h(k)+1,… mod n. It is cache-friendly but clusters; deletion needs tombstones, not an ordinary empty slot.

Comparison

Balanced BST lookup Θ(log m) worst-case and ordered iteration. Binary search is Θ(log m) but needs sorted random-access data. Hash table is expected Θ(1), worst Θ(m). Bloom lookup uses k bit probes: Θ(k), treated as Θ(1) for fixed k.

insert xh₁(x)=1h₂(x)=4h₃(x)=8query y010010001012345678h₁(y)=1 → bit[1]=1 ✓ continueh₂(y)=4 → bit[4]=1 ✓ continueh₃(y)=6 → bit[6]=0 → definitely absent
Insert sets all k positions. Query checks each indexed bit; the first zero is a proof of absence. All ones would mean only “possibly present”.

Bloom probability model

P(bit still 0) = (1−1/n)^(km) ≈ e^(−km/n)
ε = [1−(1−1/n)^(km)]^k ≈ (1−e^(−km/n))^k
k* = (n/m)ln2
n required ≈ −m ln ε /(ln2)²

Symbols: n bits, m inserted elements, k independent uniform hash functions, ε false-positive probability. These are counts/probabilities—no units. The approximation assumes large n and ideal hashing.

Order: if choosing k, calculate real k*, test floor and ceiling with the requested exact/approximate formula, then state the better integer. More hashes are not always better: they also fill more bits.

Latest exam Problem 2(b–e) — complete

(b) A Bloom filter is a bit array plus k hash functions for space-efficient approximate membership. Insert sets all hashed bits; query checks them. A zero gives a definite “not present”; all ones give “possibly present”. Standard Bloom filters have false positives, not false negatives, and do not support ordinary deletion.

(c) Insert/query take Θ(k), or Θ(1) for fixed k; compare balanced BST Θ(log m) worst-case and hash table expected Θ(1) but with exact membership and stored keys.

(d) Statements: independent of mfalse; decreases as n increases — true; false result guarantees absence — true; k=(n/m)ln2true as the continuous optimum (then choose an integer).

(e) n=24,m=5:

k*=(24/5)ln2=3.327106
ε₃=(1−e^(−15/24))³=0.100375
ε₄=(1−e^(−20/24))⁴=0.102195

Choose k=3; approximate false-positive rate 10.04%. If the exact finite-n model is requested, substitute (1−1/24)^15 instead of e^(−15/24) and label it exact.

The optimum near 3.33 makes 3 plausibly better than 4; both probabilities are in [0,1].

Tutorial Bloom exercise: exact versus approximation

For the source’s n=10 bits, m=3 inserted elements, k=3:

exact ε=[1−(9/10)^9]^3=0.229873
approx ε≈(1−e^(−0.9))³=0.208982

The approximation reported in the source is about 20.9%; the exact idealized finite-array expression is about 23.0%. The difference is visible because n=10 is small. Use the formula the question specifies; never silently call the approximation exact.

⚔ From the real exams — drill it

Hash-table drawing and the UnsortedTableMap method are old reliables; the Bloom-filter chain (concept → multiple choice → derivation → numeric instance) is the newest recurring block — it filled half of a 25-point problem in each of the two most recent exams.

2024 SUMMER · P2(a) · 4 PTS  ·  ALSO 2021 · 2020–21🔴 Exam-core
Exam 2024 Summer Problem 2(a): add exactly one method to UnsortedTableMap so obj[k] = v adds or updates a pair — MapBase and UnsortedTableMap code given
Exam 2024 Summer.pdf · Problem 2(a) — the course's MapBase/UnsortedTableMap classes
✍ Exam answer
def __setitem__(self, k, v):
    for item in self._table:
        if k == item._key:          # key exists → update
            item._value = v
            return
    self._table.append(self._Item(k, v))   # new key → add
Why that earns the marks

obj[k] = v syntax → the dunder __setitem__; that name is half the marks. The other half: handle both verbs in “add or update” — scan for the key first, only append when absent. O(n) per operation is fine here; that's the point of the unsorted table (the hash table in (b) is the fix).

→ A4 sheet: obj[k]=v → __setitem__ · obj[k] → __getitem__ · len() → __len__ · for..in → __iter__
2024 SUMMER · P2(b)+(c) · 5 PTS🔴 Exam-core
Exam 2024 Summer Problem 2(b): draw the 11-entry hash table using h(i)=(3i+2) mod 11 for keys 13,41,19,88,23,94,11,39,5 with chainingExam 2024 Summer Problem 2(c): create a nested dictionary d[key1][key2] = value in Python
Exam 2024 Summer.pdf · Problem 2(b)–(c)
✍ Exam answer
h(i) = (3i+2) mod 11:
13→8  41→4  19→4  88→2  23→5  94→9  11→2  39→9  5→6

bucket: 0  1  2      3  4      5   6  7  8   9      10
        —  —  88,11  —  41,19  23  5  —  13  94,39  —

(c) d = {}; d[k1] = {}; d[k1][k2] = v — or from collections import defaultdict; d = defaultdict(dict).

Why that earns the marks

Pure calculator work: 3i+2, then the mod-11 remainder — write the h(i) line per key (that's the “supported” part), then the bucket table with chains in insertion order. Collisions here: buckets 2, 4, 9 each chain two keys. Every value machine-verified. The nested-dict two-pointer: plain dict needs the inner dict created first; defaultdict(dict) does it automatically.

→ A4 sheet: chaining: list per bucket · load α = m/n · expected O(1+α) · defaultdict(dict) for nesting
2025 SUMMER · P1(e)+(f) · 8 PTS🔴 Exam-core
Exam 2025 Summer Problem 1(e): describe a Bloom filter, how it applies to the username-lookup problem, and its complexityExam 2025 Summer Problem 1(f): multiple choice — which statements about Bloom filter performance are true
Exam 2025 Summer.pdf · Problem 1(e)–(f)
✍ Exam answer

(e) Bit array of n bits + k hash functions. Insert x: set bits h₁(x)…h_k(x). Query x: all k bits 1 → “probably in S”; any bit 0 → “definitely not in S”. False positives possible, false negatives impossible. Time O(k) = O(1) per op; memory n bits ≪ storing S → keep the filter in RAM as a prefilter for the 10⁹ usernames, hit disk only on (rare) positives. Faster than binary/BST O(log n), comparable to hashing but far smaller.

(f) True: 2 (more bits → lower FP rate), 3 (a 0-bit proves absence), 4 (k* = (n/m)·ln 2). False: 1 — FP probability grows with m.

Why that earns the marks

The (e) description has a fixed skeleton the examiner looks for: structure (bits + k hashes), the two operations, the asymmetry (FP yes / FN no), the complexity, and the application sentence tying it to the story. The MC options are recycled across years with the same four claims — memorize which is the false one: FP depends on m (the fuller the filter, the more false positives).

→ A4 sheet: Bloom: n bits, k hashes · ins: set k bits · query: all 1 ⇒ maybe, any 0 ⇒ NO · FP yes/FN no · O(k)
2025 SUMMER · P1(g) · 5 PTS + 2025–26 RESIT · P2(e) · 3 PTS🔴 Exam-core
Exam 2025 Summer Problem 1(g): guided derivation of the probability a bit stays 0, ending with approximating (1-1/n)^(n·k/n)Exam 2025-26 Resit Problem 2(e): m=5 elements, n=24 bits — optimal integer k and false positive rate
Exam 2025 Summer.pdf · P1(g) + Exam 2025-26 Winter Resit.pdf · P2(e)
✍ Exam answer

Derivation: (1−1/n)n·k/n ≈ e−k/n, because (1−1/n)n → 1/e for large n.

Numeric (m=5, n=24): k* = (n/m)·ln 2 = (24/5)·0.693 = 3.33 → k = 3 (integer).
ε = (1 − e−km/n)k = (1 − e−15/24)³ = (1 − 0.535)³ = 0.465³

k = 3, ε ≈ 0.100 ≈ 10%
Why that earns the marks

The guided derivation only wants the limit identity (1−1/n)n ≈ e−1 applied to the exponent the question already arranged for you. The numeric instance is the full pipeline: k* formula → round to integer (the statement demands it — 3.33 → 3; checking k=3 vs k=4 both is the safe move, k=3 gives ε≈10.0%, k=4 ≈10.1%, so 3 wins) → plug into the FP formula with your integer k, not 3.33. All numbers machine-verified. Keep 3+ digits through the calculation, round at the end.

→ A4 sheet: P(bit=0)=(1−1/n)^km ≈ e^−km/n · ε=(1−e^−km/n)^k · k*=(n/m)ln2 (round, test neighbors!) · (1−1/n)^n≈1/e
Chapter 8

Akra–Bazzi, Strassen and selected topics

🔴 Exam-core The selected-topics tutorial explicitly limits exam relevance to Bloom filters, selection and median-of-medians, but the latest exam also asks Strassen. Learn its algebra and recurrence.

Akra–Bazzi for unequal subproblems

T(x)=Σᵢ aᵢT(bᵢx)+g(x)
find p from Σᵢ aᵢbᵢ^p=1
T(x)=Θ(x^p(1+∫₁ˣ g(u)/u^(p+1) du))

Assumptions: aᵢ>0, 0<bᵢ<1, regularity conditions, and lower-order perturbations do not dominate. Cue: recursive fractions differ, so Master theorem cannot apply.

Worked: for median-of-medians, T(n)=T(n/5)+T(7n/10)+Θ(n). Solve (1/5)^p+(7/10)^p=1 numerically, p≈0.8398. With g(u)=u, the integral is ∫u^(−p)du=Θ(n^(1−p)); multiplied by n^p gives Θ(n).

If you report only Θ(n^p), you forgot the combine-work integral.

Latest exam Problem 3(c–g) — matrix multiplication and Strassen

(c) Naive: each of output entries is a dot product of length n, so Θ(n³) scalar operations.

(d) Block product:

C₁₁=A₁₁B₁₁+A₁₂B₂₁ C₁₂=A₁₁B₁₂+A₁₂B₂₂
C₂₁=A₂₁B₁₁+A₂₂B₂₁ C₂₂=A₂₁B₁₂+A₂₂B₂₂

(e) Verify C₂₁: from the definitions M₂=(A₂₁+A₂₂)B₁₁ and M₄=A₂₂(B₂₁−B₁₁):

M₂+M₄=A₂₁B₁₁+A₂₂B₁₁+A₂₂B₂₁−A₂₂B₁₁
=A₂₁B₁₁+A₂₂B₂₁=C₂₁

(f) Seven half-size multiplications plus matrix additions: T(n)=7T(n/2)+Θ(n²).

(g) Master theorem: a=7,b=2,c=log₂7≈2.807355. Since n²=O(n^(c−ε)) for e.g. ε≈0.8, Case 1 gives T(n)=Θ(n^(log₂7))≈Θ(n^2.807).

It must beat cubic asymptotically because 2.807<3, but constants mean it need not win for tiny matrices.

⚪ Low priority Random-number generation, fast inverse square root, prime-number background, Coppersmith–Winograd and AlphaTensor provide context in the slides but were not selected as exam-relevant by the SS26 selected-topics tutorial. Know only their purpose if time remains.

⚔ From the real exams — drill it

The Strassen chain — naive complexity → block partition → correctness check → recurrence → Master theorem — has appeared as a near-verbatim 18-point run in three of the last four exams. It is the most predictable derivation in the course.

2024–25 RESIT · P2(c)+(d) · 7 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 2(c): worst-case complexity of naive matrix multiplication with justificationExam 2024-25 Resit Problem 2(d): partition A, B, C into block matrices and define how to calculate C11, C12, C21, C22
Exam 2024-25 Winter Resit.pdf · Problem 2(c)–(d)
✍ Exam answer

(c) O(n³) — C has n² entries; each is a dot product of a row and a column: n multiplications. n²·n = n³.

(d) Standard block multiplication:

C11 = A11·B11 + A12·B21     C12 = A11·B12 + A12·B22
C21 = A21·B11 + A22·B21     C22 = A21·B12 + A22·B22
Why that earns the marks

(c) is bound + justification in one line — the n² × n sentence is the “supported” part. (d): block matrices multiply exactly like 2×2 numbers, just with matrix blocks — row-times-column at block level. 8 block multiplications of half size; that's the setup Strassen improves on (8 → 7).

→ A4 sheet: naive matmul O(n³) (n² entries × n each) · blocks: Cij = Ai1·B1j + Ai2·B2j
2024–25 RESIT · P2(e) · 4 PTS🔴 Exam-core
Exam 2024-25 Resit Problem 2(e): the 7 Strassen auxiliary matrices M1..M7 and the Cij recombination — show C21 is calculated correctly
Exam 2024-25 Winter Resit.pdf · Problem 2(e) — M₁…M₇ and the recombination are given in the exam
✍ Exam answer
C21 = M2 + M4
    = (A21+A22)·B11 + A22·(B21−B11)
    = A21·B11 + A22·B11 + A22·B21 − A22·B11
    = A21·B11 + A22·B21   ✓  (matches block formula)
Why that earns the marks

Substitute the given M-definitions, expand (distributivity holds for matrices), cancel the ±A22·B11 pair, and land on the block formula from (d) — then say that's what it had to equal. Four lines, no cleverness. Note: the M₁…M₇ definitions and the Cᵢⱼ recombination are always printed in the exam — never memorize them; only the expansion technique and the target (the (d) formulas) matter. The exam has asked C1,1 and C2,1 in different years — same three moves.

→ A4 sheet: Strassen check: substitute given M's → expand → cancel → block formula (M's are provided, don't copy them)
2024–25 RESIT · P2(f)+(g) · 7 PTS  ·  ALSO 2025–26 R · 2023 S · 2021 S🔴 Exam-core
Exam 2024-25 Resit Problem 2(f): provide the recurrence relation of the Strassen algorithmExam 2024-25 Resit Problem 2(g): derive the worst-case complexity from the recurrence
Exam 2024-25 Winter Resit.pdf · Problem 2(f)–(g)
✍ Exam answer

(f) T(n) = 7·T(n/2) + O(n²) — 7 half-size multiplications + matrix additions.

(g) Master theorem, T(n) = a·T(n/b) + O(nd): a=7, b=2, d=2. Applicable: a≥1, b>1, f polynomial.
Compare d vs log_b a: log₂7 ≈ 2.807 > 2 = d → recursion-dominated case.

T(n) = O(nlog₂7) ≈ O(n2.807) — beats naive O(n³).
Why that earns the marks

The cover-sheet rule bites precisely here: “if you use a fundamental theorem you must indicate this and explain why it applies.” So the full-marks skeleton is: name (Master theorem) → parameters (a=7 subproblems, b=2 size divisor, d=2 from the additions) → applicabilitycase comparison (log₂7 > d) → resultinterpretation (asymptotically faster than n³). Same chain answers merge sort (a=2,b=2,d=1 → n log n) and binary search (a=1,b=2,d=0 → log n) — one memorized procedure, three recurring exams questions.

→ A4 sheet: the Master theorem block: T=aT(n/b)+O(n^d): d>log_b a → n^d · d=log_b a → n^d log n · d<log_b a → n^log_b a + instances Strassen 7/2/2→n^2.807 · merge 2/2/1→n log n · binary 1/2/0→log n
Chapter 9

Quantum computing: broad, precise fundamentals

🔴 Exam-core Revision says quantum appeared in the last three exams with different questions. Prepare qubits, measurement, gates, reversibility, decoherence, Grover and Shor—not one memorized paragraph.

Valid qubit and measurement

|ψ⟩=α|0⟩+β|1⟩ = [α,β]ᵀ
α,β ∈ ℂ, |α|²+|β|²=1
P(0)=|α|², P(1)=|β|²

Meaning: amplitudes α,β are complex numbers, not probabilities; squared magnitudes are probabilities. A classical bit has a definite 0 or 1. A qubit may be in a coherent superposition until measured; measurement returns a classical outcome and changes the state.

Validity check: compute complex magnitude |a+bi|²=a²+b²; totals must equal 1 (within rounding).

Worked qubit

Let α=1/√3 and β=i√(2/3). Then |α|²=1/3, |β|²=2/3; total 1, so valid. Measurement gives 0 with probability 1/3, 1 with 2/3.

Hadamard and X

X=[[0,1],[1,0]]
H=(1/√2)[[1,1],[1,−1]]

X|0⟩=|1⟩. H|0⟩=(|0⟩+|1⟩)/√2. Quantum gates are unitary, hence reversible; measurement is not a unitary reversible gate.

Grover

Find a marked item in an unstructured space of size N using about Θ(√N) oracle calls versus classical Θ(N). It is a quadratic, not exponential, speedup. Assumes oracle access and high-probability success.

Shor

Factors integer N by reducing factoring to period finding, then using the quantum Fourier transform. Course slides give polynomial time roughly O((log N)²(log log N)(log log log N)) for the quantum arithmetic model, versus the best known classical general number-field sieve, sub-exponential in N. State the cost model; do not say classical factoring is simply O(2ⁿ) without defining n.

Latest exam Problem 3(a–b) — exam-ready answer

(a) α,β are complex probability amplitudes. A valid qubit satisfies |α|²+|β|²=1; measurement yields 0/1 with those probabilities. Unlike a classical bit, the pre-measurement state can be a coherent superposition and can exhibit interference.

(b) Shor’s algorithm is a quantum integer-factoring algorithm using modular exponentiation, period finding and the QFT. It runs in polynomial time in the input bit-length under the course cost model, whereas the best known general classical factoring algorithm is sub-exponential but super-polynomial; therefore it provides a super-polynomial speedup and threatens RSA for sufficiently capable fault-tolerant quantum computers.

Reversibility

Unitary gates preserve information and inner products, so every gate has inverse U†. Classical AND is not reversible without extra bits because several inputs share an output.

Decoherence

Uncontrolled environment interaction destroys usable phase relationships, turning coherent superposition into classical-looking mixtures and causing errors. Isolation, fast control and error correction combat it.

Adiabatic vs gate model

Gate model applies discrete unitary gates. Adiabatic computing evolves a Hamiltonian slowly from an easy ground state to one encoding the solution. D-Wave hardware context is ⚪ Low priority.

⚔ From the real exams — drill it

The qubit-definition question is word-for-word identical in the last three exams; Grover and Shor alternate. This is the cheapest 7 points in the exam if the three sentences are ready.

2024–25 RESIT · P2(a) · 4 PTS  ·  VERBATIM IN 2025–26 R · 2023 S🔴 Exam-core
Exam 2024-25 Resit Problem 2(a): qubit vector representation — explain α and β, what makes a qubit different from a bit, and the validity constraint
Exam 2024-25 Winter Resit.pdf · Problem 2(a)
✍ Exam answer

α, β are complex probability amplitudes of the basis states |0⟩ and |1⟩. A bit is 0 or 1; a qubit is a superposition of both until measured — measurement yields 0 with probability |α|², 1 with |β|².
Constraint: |α|² + |β|² = 1 (α, β ∈ ℂ) — probabilities must sum to 1.

Why that earns the marks

Three graded atoms: what α/β are (amplitudes, with the |·|²-gives-probability link), the bit-vs-qubit difference (superposition + collapse on measurement), and the normalization constraint. Your old handwritten sheet had exactly |α|²+|β|²=1 — kept. If gates appear (older exams): X = [[0,1],[1,0]] flips amplitudes (NOT); Hadamard H = (1/√2)[[1,1],[1,−1]] maps |0⟩ to (|0⟩+|1⟩)/√2 — an equal superposition.

→ A4 sheet: |a⟩=α|0⟩+β|1⟩ · α,β∈ℂ amplitudes · P(0)=|α|², P(1)=|β|² · |α|²+|β|²=1 · X=[0 1;1 0] · H=1/√2[1 1;1 −1]
2024–25 RESIT · P2(b) · 3 PTS (GROVER) + 2025–26 RESIT · P3(b) · 3 PTS (SHOR)🔴 Exam-core
Exam 2024-25 Resit Problem 2(b): what is Grover's algorithm — explanation and speedup in O notationExam 2025-26 Resit Problem 3(b): what is Shor's algorithm — explanation and speedup
Exam 2024-25 Winter Resit.pdf · P2(b) + Exam 2025-26 Winter Resit.pdf · P3(b) — the two alternate
✍ Exam answer

Grover: quantum search over n unstructured items using amplitude amplification — repeated oracle + reflection steps boost the marked item's amplitude. Finds it in O(√n) oracle queries vs classical O(n) — a quadratic speedup.

Shor: quantum integer factorization via the quantum Fourier transform (period finding). Runs in polynomial time, ≈ O((log N)³), vs super-polynomial (sub-exponential) best known classical — an exponential speedup; breaks RSA-style cryptography.

Why that earns the marks

Both follow the same 3-sentence template the question dictates: what problem + one mechanism phrase + speedup in O notation with the classical comparison. The classification pair to keep straight: Grover = quadratic (search), Shor = exponential (factoring). In the 2025 Summer context question (“how could a quantum computer do the lookup?”) the answer is Grover applied to the unsorted username set: O(√n) instead of O(n).

→ A4 sheet: Grover: unstructured search O(√n) vs O(n), quadratic · Shor: factoring poly O((log N)³) vs super-poly, exponential, breaks RSA
Chapter 10

Transfer mock: three new combinations

🔴 Exam-core Set 90 minutes, choose two problems, and write complete working. These are generated from recurring source families but use new combinations to resist pattern memorization.

Problem 1 · Code, graphs and complexity (25)

  1. (8) Write a generator that yields a singly linked list in reverse order without changing it. State time and auxiliary space.
  2. (8) Run Dijkstra from S on edges S–A:2, S–B:5, A–B:1, A–C:6, B–C:2. Give settle order, distance table and path S→C.
  3. (9) Solve T(n)=3T(n/2)+n log n and justify the theorem case.
Full solution · Problem 1

1

def reverse_values(self):
    stack = []
    current = self.head
    while current is not None:
        stack.append(current.element)
        current = current.next_element
    while stack:
        yield stack.pop()

Each node is visited/pushed/popped once: Θ(n) time, Θ(n) auxiliary space. A singly linked list has no backward pointers, so preserving the list while reversing output requires stored history (or recursion with the same asymptotic stack).

2

Start (S=0,A=∞,B=∞,C=∞). Settle S → A=2,B=5. Settle A → B=min(5,3)=3,C=8. Settle B → C=min(8,5)=5. Settle C. Order S,A,B,C; path S–A–B–C, cost 5.

3

a=3,b=2,c=log₂3≈1.585. f(n)=n log n=O(n^(c−ε)), e.g. any small ε<0.585 eventually dominates the logarithm. Master Case 1: Θ(n^(log₂3)).

Problem 2 · ID3, Bloom and probing (25)

  1. (12) For rows (A,x,+), (A,y,+), (B,x,−), (B,y,+), compute gains of attributes first and second; draw the ID3 tree with an explicit tie policy.
  2. (7) A Bloom filter has n=80,m=10. Choose integer k and approximate ε.
  3. (6) Insert keys 18, 29, 40, 22 into an 11-slot table using h(k)=k mod 11 and linear probing. Show slots.
Full solution · Problem 2

1

Parent labels 3+,1−: H=−¾log₂¾−¼log₂¼=0.8113. First attribute: A branch (2+,0−), B branch (1+,1−); remainder ½·0+½·1=0.5, gain 0.3113. Second attribute: x branch (1+,1−), y branch (2+,0−), same remainder/gain. Tie: choose first by column order. A→+, B then split on second: x→−, y→+.

2

k*=8ln2=5.545. Test 5 and 6: ε₅=(1−e^(−50/80))⁵≈0.02168; ε₆=(1−e^(−60/80))⁶≈0.02158. Choose k=6, about 2.16%.

3

18→7; 29→7 occupied, so 8; 40→7 occupied, 8 occupied, so 9; 22→0. Final: slot 0:22, 7:18, 8:29, 9:40.

Problem 3 · Selection, Strassen and quantum (25)

  1. (9) Explain why the median-of-medians pivot discards a constant fraction and solve its recurrence.
  2. (8) Expand M₃+M₅ to verify Strassen’s C₁₂; derive complexity.
  3. (8) Determine whether [1/2, (√3/2)i]ᵀ is a valid qubit, give measurement probabilities, then contrast Grover and Shor speedups.
Full solution · Problem 3

1

At least half the group medians are ≥ the median-of-medians, and each such full group contributes at least three elements ≥ it; similarly below it. Ignoring a constant number of incomplete/pivot groups, each side discards about 3n/10, so the larger recursive side is at most 7n/10+O(1). Recurrence T(n)≤T(n/5)+T(7n/10)+Θ(n)=Θ(n) by Akra–Bazzi as shown earlier.

2

M₃=A₁₁(B₁₂−B₂₂), M₅=(A₁₁+A₁₂)B₂₂. Sum = A₁₁B₁₂−A₁₁B₂₂+A₁₁B₂₂+A₁₂B₂₂=C₁₂. Recurrence 7T(n/2)+Θ(n²) gives Θ(n^log₂7).

3

|1/2|²+|(√3/2)i|²=1/4+3/4=1: valid. P(0)=1/4,P(1)=3/4. Grover gives quadratic query speedup Θ(N)→Θ(√N) for unstructured search. Shor gives polynomial-time quantum factoring in bit-length versus best known classical super-polynomial/sub-exponential factoring: a super-polynomial speedup.

Self-mark rule

Give yourself no calculation marks for a naked final number. A full-mark line contains the formula/theorem, mapped symbols, applicability, substitution, result, and one check or interpretation. For code, run the empty, one-element, ordinary, and boundary cases mentally.

Handwrite after studying

One-side A4 synthesis

This is deliberately compressed and should be copied by hand only after you can explain each line. Use the button to print just this page as a drafting template.

Asymptotics

Order: 1 ≺ log n ≺ n ≺ n log n ≺ n² ≺ n³ ≺ cⁿ ≺ n!. O upper, Ω lower, Θ tight. Recursive stack space Θ(depth).

Master

T=aT(n/b)+f; c=log_ba

f polynomially smaller → Θ(nᶜ). f=Θ(nᶜlogᵏn) → Θ(nᶜlogᵏ⁺¹n). f larger + regularity → Θ(f).

Akra–Bazzi

Σ aᵢ bᵢᵖ = 1
T = Θ(nᵖ · (1 + ∫₁ⁿ g(u)/uᵖ⁺¹ du))

Sort

merge Θ(n log n), stable, Θ(n) space; quick expected Θ(n log n), worst n², unstable; heap Θ(n log n), in place, unstable; comparison lower bound Ω(n log n). Stable preserves equal-key order.

Selection

Quickselect avg Θ(n), worst n². MoM groups 5; pivot median of medians; recurrence T(n/5)+T(7n/10)+Θ(n)=Θ(n).

Lists/ADTs

Array index Θ(1), middle Θ(n), append amortized Θ(1). Linked access Θ(n), insert with predecessor Θ(1). Stack LIFO; queue FIFO; deque both. Pointer insert: new.next=prev.next; prev.next=new; size++.

Graphs

Adj list space V+E; matrix V². BFS unweighted shortest; Dijkstra nonnegative: settle min tentative, relax d[v]>d[u]+w. Heap O((V+E)logV).

Trees/ID3

Traversal Θ(n), stack Θ(h). Balanced BST operations Θ(log n), degenerate Θ(n).

H=−Σp log₂p
Rem(A)=Σ|Sᵥ|/|S|H(Sᵥ)
IG=H(parent)−Rem

Calculator: log₂x=ln x/ln2. Max IG; recurse impure branches; state ties.

Hash/Bloom

Hash expected Θ(1), worst Θ(m). Chaining; probing (tombstone delete).

ε≈(1−e^(−km/n))ᵏ
k*=(n/m)ln2
n≈−m lnε/(ln2)²

Any zero = definitely absent; all ones = maybe. No false negatives normally. Check floor/ceil k.

Strassen

Naive Θ(n³). 7 half products + Θ(n²): T=7T(n/2)+n²=Θ(n^log₂7)≈n^2.807. Know M₂+M₄=C₂₁ expansion.

Quantum

|ψ⟩=α|0⟩+β|1⟩; |α|²+|β|²=1

P(0)=|α|². X swaps; H creates/interferes superposition. Gates unitary/reversible; measurement not. Grover Θ(√N) vs Θ(N). Shor polynomial in bit-length vs classical sub-exp. Decoherence = environment destroys phase.

Exam script

Name theorem → map parameters → check assumptions → substitute → result → sanity check. 4 min choose; 38 min each; 10 min check. Unsupported answer = no credit.

Designed from the supplied one-sided old cheat-sheet example, but rewritten around SS26 revision emphasis.DERIVED EXPLANATION
Reference

Notation and compact glossary

n — input size; in Bloom formulas specifically number of bits. Never assume the same meaning across questions.

m — often inserted elements in Bloom filters; sometimes edges or another count. Define it.

k — rank in selection, hash-function count in Bloom, or logarithmic exponent in Master Case 2.

|V|, |E| — graph vertex and edge counts.

h — tree height or hash function, by context.

α — load factor in hashing, or complex amplitude in a qubit. Context is essential.

ε — positive comparison gap in theorem cases, or Bloom false-positive probability.

ADT — abstract data type: behavior/operations independent of implementation.

Amortized — average per operation over any worst-case sequence, not probabilistic average-case.

Auxiliary space — extra working memory, normally excluding input/output storage.

Invariant — property true before and after each iteration/mutation.

Stable sort — equal-key records keep relative input order.

Relax — improve a tentative shortest-path estimate through an edge.

Entropy — uncertainty in a categorical distribution; base-2 units are bits.

False positive — reports possibly present when absent. Bloom filters permit these.

Qubit — normalized complex two-amplitude state; measurement yields a classical bit.

Documented source discrepancies: the Revision Part 1 geometric recurrence expansion loses powers of 4; corrected above. Bloom notes sometimes move between exact and exponential approximations without labeling the switch; both are separated above. Recursive tree-inversion space is Θ(h), not invariably Θ(n). Shor complexity depends on the arithmetic/circuit cost model; the book states the course expression with that caveat.

Scope traced to Syllabus, p. 1, Slides, pp. 1–738, all Tutorial-SS26 sheets and solutions, Coursework, and supplied exams 2020–2025/26. Professor-slide screenshots are not reproduced; all diagrams here are original SVG.

★ 19 July call — the night before

What the professor said — use this to finish tonight

🔴 Prof-confirmed From a direct call with Prof. Glauner on 19 July. Everything below is his framing, not inference from past exams — where it refines or overrides earlier chapters, this section wins. Items marked IN he stated will appear; OUT he stated will not.

Tonight's 90 minutes, in his order of value

  1. ID3 full tree, 15 of 25 pts — rehearse one complete build (drill). His words: “if you do the decision tree learning right, it's 15 points… you need 20 to pass.” Bigger dataset than last time (more attributes = more points), so practice the 6-attribute 2024–25 resit instance.
  2. Akra–Bazzi with an easy integer p — one guaranteed problem (worked recipe below).
  3. Bloom filter, applied — re-do Tutorial-SS26\8-Selected-Topics\BloomFilterExercises.pdf; he said the exam task is “quite similar.”
  4. Symmetric trees — write is_symmetric + mirror once from memory (drill).
  5. Hash table by chaining, graph definition + adjacency matrix, Deggendorf-style recursion — one pass each (hash · graphs · recursion).
  6. Quantum BogoSort — read the one paragraph below; that is the whole quantum scope.

Confirmed topic by topic

IN Akra–Bazzi — one dedicated problem

“There will be one problem about Akra–Bazzi… you need to find the p, and the p will be a very small integer.” Expected flow: a recurrence is given → first argue whether the Master theorem applies (it won't — unequal subproblem sizes) → then solve with Akra–Bazzi. Full recipe in the box below.

IN ID3 — full tree, 15 points

Complete decision-tree build with intermediate steps on a fresh dataset. Budget ~25 minutes. Pure branches: write “pure → leaf,” no arithmetic. State ties. Your drilled procedure is exactly what's needed.

IN Bloom filter — “super important,” applied

Given hash values for keys: set bits in the array, then query — any 0-bit ⇒ “definitely not in S”; all 1 ⇒ “probably in S.” Know the theory too, but he “will not quiz” the ε-derivation this time. Crucial: complexity is O(k) — depends on the number of hash functions, not the number of elements — and compare it to the other lookup structures.

IN Hash tables — apply, don't implement

“You're given a hash function and some keys, insert them into a hash table and think about the collisions… we mainly worked with chaining.” Exactly the 2024 Summer P2(b) drill with new keys. No hash-function design, no code.

IN Graphs — formal definition + adjacency matrix

“Just a different graph.” Same two moves as the 2025 Summer drill: k-tuple G=(V,E,w) with explicit sets, then the matrix with a declared row-convention.

IN Symmetric trees — determine + implement recursively

“Very important for tomorrow… a tree is symmetric if it's equal to its inverse. Sometimes I copy-paste stuff from past exams.” Structure only, values ignored — the whole is_symmetric incl. outer function, as in the 2024–25 resit drill.

IN Recursion — Deggendorf-style + lab problems

“For recursive functions… these Deggendorf numbers from the past exams, something like this,” plus the lab-problems video he shared. Keep the naive → complexity → memo → lru_cache chain hot (drill).

IN Quantum — small, combined with sorting

One playful task: quantum BogoSort (below). “That's all about quantum computing this year.” Keep the qubit definition ready anyway — it costs one line on your sheet and has appeared verbatim three exams running.

OUT Dropped this year — stop drilling these tonight

  • Strassen: “not part of this year's exam” (selected topics = only what was discussed: Bloom, selection, median-of-medians).
  • Median-of-medians: “nothing specific in the exam,” no code — it served to motivate Akra–Bazzi.
  • Bloom ε-derivation quiz: “I will not quiz you on this stuff” — the applied run-through replaces it.
  • Hash-table implementation code: apply a given hash function only.

No comment given — stay lightly ready

Lists/arrays/ADTs: “I'm not commenting on that.” Keep __iter__, remove_first, and the MyArray patterns on your sheet — they're cheap insurance and recur historically. Format unchanged: 90 min, 2 of 3 × 25 pts, 20 to pass, one handwritten A4 side + non-CAS calculator.

The Akra–Bazzi recipe he described — finding p without pain

When Master fails: Master needs every subproblem to have the same size divisor (one b). A recurrence like T(n) = T(n/5) + T(7n/10) + O(n) splits unevenly → say exactly that, then switch to Akra–Bazzi:

T(n) = Σᵢ aᵢ·T(n/bᵢ) + g(n)  →  find p with  Σᵢ aᵢ·(1/bᵢ)ᵖ = 1  →  T(n) = Θ( nᵖ · (1 + ∫₁ⁿ g(u)/u^{p+1} du) )

Finding p (his exact guidance: “a very small integer — try p = 1, 2, 3”): the three tests cost seconds each:

  • p = 0 works ⇔ Σ aᵢ = 1
  • p = 1 works ⇔ Σ aᵢ/bᵢ = 1  (sum of the fractions of n equals 1 — e.g. T(n/2)+T(n/3)+T(n/6): ½+⅓+⅙ = 1 ✓)
  • p = 2 works ⇔ Σ aᵢ/bᵢ² = 1  (e.g. 3T(n/2)+4T(n/4): ¾ + 4/16 = 1 ✓)
  • None hits? Bracket it on the calculator like binary search on p (he confirmed 0.8398 for median-of-medians this way) — “but that would not happen in the exam.”

Then skip the integral — for g(n) = Θ(n^d) the result collapses to a Master-like trichotomy (this is what the integral evaluates to):

d > p → Θ(n^d)  ·  d = p → Θ(nᵖ · log n)  ·  d < p → Θ(nᵖ)
Worked, exam-shaped: T(n) = T(n/2) + T(n/3) + T(n/6) + n. Master? No — three different divisors. Akra–Bazzi: try p=1: ½+⅓+⅙ = 1 ✓. g(n)=n → d=1 = p → T(n) = Θ(n log n).
Reference (course example): median-of-medians T(n)=T(n/5)+T(7n/10)+O(n): p≈0.84 < 1 = d → Θ(n) — linear-time selection.

Write in this order: (1) “Master theorem not applicable — unequal split sizes.” (2) The Σ aᵢ(1/bᵢ)ᵖ = 1 line with your integer test shown. (3) The trichotomy comparison d vs p. (4) Boxed Θ. That is the “name the theorem + why it applies” structure the cover sheet demands.

Quantum BogoSort — the whole quantum question

Classical BogoSort: shuffle the list; check if sorted (O(n)); repeat until sorted by chance. Best case O(n) (already sorted), expected O(n·n!) (n! orderings, one is sorted), worst case unbounded — a deliberately absurd algorithm.

Quantum BogoSort (the joke he described): use quantum randomness to put the list into a superposition of all n! permutations simultaneously; observe/measure. In the branch where the measurement finds it sorted, you're done after one shuffle — O(n) total, the cost of the sortedness check. (The punchline version: if it's not sorted, destroy the universe — in every surviving universe the list is sorted.) The serious sentence to close with: it's not a real algorithm — measurement collapses to one random permutation, so this is a parody of “quantum = try everything at once,” not a usable speedup; contrast Grover, which gives a genuine but only quadratic O(√n) advantage.

Source: call with Prof. Glauner, 19 Jul 2026, evening before the exam. Kept verbatim where quoted; complexity claims independently checked (p = 0.8398 for median-of-medians recomputed numerically).PROF INSISTED
Primary source

The call itself — 19 July, transcript

🟡 Context The raw material behind the briefing above. Reconstructed from an automatic transcription of the call: speaker attribution inferred, wording lightly cleaned where the ASR garbled it, small talk kept as asides. Where the briefing paraphrases, this is what was actually said.

▸ Open the full formatted transcript — Akra–Bazzi · exam format · hashing & Bloom · ID3 · symmetric trees · quantum · logistics

Opening · Akra–Bazzi and finding p

PROF You have done well in so many advanced courses, so we want you to succeed with this thing tomorrow.

ALEX I have a couple of questions on topics I don't fully understand. I understand the formulas and how to apply them — for example Akra–Bazzi — but I don't quite understand how to find the p, or how you choose a p. It's shown in the slides, I think. Maybe I can share my screen and you show me where the p comes from. The tutorial slides just… already give a p.

[screen share; searching the slides for “Akra” — nothing found at first; it's near the end of Selected Topics]

ALEX Your slide count has grown — I remember ~300 slides, now it's ~700.

PROF It's a lot of selected material, and we don't do all the selected topics every year. The other chapters grew a little… we're at the Bloom filter here, and just after it comes selection.

ALEX Selection was just a 20-minute video, so I assumed it won't really appear — or only very simply.

PROF Selection is the basis; then we saw how to speed it up, and for that we looked at the median of medians. And Akra–Bazzi is here.

ALEX As I understood it, Akra–Bazzi is just an alternate way of finding algorithm complexity?

PROF Not the ultimate way — it's a generalization of the Master theorem for this type of recurrence. And that depends on your recurrence: you have your a's and b's, and then the sum — a·(1/b)ᵖ terms — like (1/5)ᵖ + (7/10)ᵖ, all equal to 1. We have one example there.

ALEX But the slides just say “approximately” — that's what I mean. How do we find the p on the calculator?

PROF Here you often don't even need a calculator. You write down the formula and try a relatively simple p — maybe 1, 2, 3 — and you find the solution quickly. If it's not a simple integer you'd need an approximation technique like Newton's method — but that's what I would not put in the exam. With a calculator you can also bracket it: try 0, then 1, then 0.5, and keep halving the interval, like binary search — that's how you'd get the 0.839 in the median-of-medians example. But that would not really happen in the exam. If you need to determine the p, it will be a relatively easy-to-find integer.

Exam format · what's in, what's out

ALEX My biggest concern: will it be like the summer 2025 exam we reviewed — applied code, guided calculations — or like the winter 24/25 exam, which was heavy on derivations — recurrences, Strassen, full ID3, everything mixed and very theory-heavy?

PROF The Strassen algorithm is not part of this year's exam — we only ask about the selected topics that were actually discussed: Bloom filter, selection, and median of medians. And median of medians includes the Akra–Bazzi method — we introduced it there because our other tools couldn't determine that recurrence's complexity.

ALEX Will there be a dedicated selected-topics problem, or will it be spread across all three like in 2020?

PROF That can happen. What I can tell you for sure — and I emphasized it in the discussion too — there will be one problem about Akra–Bazzi. You need to find the p, and the p will be a very small integer. You write down that formula we had and find it very easily.

ALEX The p was my biggest problem with Akra–Bazzi. Where will it appear — in which form?

PROF You'll be given a recurrence relation and need to determine its complexity. First think about whether it can be solved with the Master theorem — you need to argue. Maybe you notice it can't. Then you may be asked to solve it with the Akra–Bazzi method.

ALEX And median of medians — I see it as mostly math and theory. I don't remember us implementing it.

PROF Oh, we implemented it — we introduced it this year and implemented it. But no, you won't be asked to write code on median of medians. And — I'll tell you this, but don't tell the others — there will be nothing specific in the exam about the median of medians. What is there is the Akra–Bazzi part, about some other recurrence relation.

Code depth · hashing & Bloom

ALEX When we're asked to implement basic functions — __iter__, remove_first, merge, the MyArray methods — I'm fine. But hash tables… I've watched that lecture three times. I get the concept of hashing and collisions, but the implementation…

PROF You don't need to implement it. There will be something about hash tables and collisions, but rather an example: you're given a hash code or a hash function, and some keys, and you insert them into a hash table and think about the collisions. There were such examples in past exams, and we have something like this this year as well.

[aside — ordering an alcohol-free Radler; birthday hotel stay; brief agreement that beer is basically water]

ALEX You said there will be new questions — how new will the exercises be?

PROF There will be problems you've seen in past exams, maybe with a new dataset, a new graph, or new keys. And some new stuff, obviously. But if you did the coursework, watched the lectures, and did the past exams, there isn't too much new. There will be something about graphs — a graph, you need the formal definition and the adjacency matrix. Just a different graph. Knowing that will be very helpful for tomorrow.

PROF We mainly worked with chaining for collisions — that's important for tomorrow as well. And hashing also connects to the Bloom filter: like in Meltem's tutorial, some strings or values need to be added into a Bloom filter, and for that you need hashing too.

ALEX With hashes, my problem was the variety — every kind of collision handling…

PROF No — this time you apply hashing and collision handling by chaining, just with an example. You don't need to write code. We also didn't discuss what a good hash function would be — you're given hash functions and apply them.

ALEX If that's the case, I assume lists, arrays, and ADTs won't appear?

PROF I'm not commenting on that. Everything we discussed in class is important, but I've highlighted a few things. Something super important this year is the Bloom filter. In the tutorial we practiced running values into a Bloom filter and determining if something is not in it or most likely in it. In past exams I asked theory or equations about it — this year you need to put it to life. Not coding — you calculate through the examples. If you did that in the tutorial, it will be quite similar. But you still need the theory. And what's crucial — we discussed it last week — the complexity of the Bloom filter does not depend on the number of elements, but on the number of hash functions: O(k), and how it compares to other algorithms and data structures for efficient lookup.

ALEX Would we also need to derive ε — the e-approximation and so on?

PROF This time I will not quiz you on this stuff. But you need to know the O(k) and what it means.

ID3 · symmetric trees

ALEX ID3 appeared last exam, so I assume this time it won't — the full calculation?

PROF Oh, it will appear with a full calculation this time. There will be a dataset — 15 points to build the whole decision tree with ID3. If you do that right, you have almost passed: you need 20 of 50 points. Last time it was 11 points because it was a smaller dataset with fewer attributes — more attributes, more points. It's 50 points for 90 minutes, so 15 points is around 25 minutes — doable with practice.

PROF And when it comes to trees — in a past exam you had to determine if trees are symmetric. That's something… knowing this for tomorrow, and how to implement it, would be very helpful. A tree is symmetric if it's equal to its inverse. You determine it for the whole tree, recursively. Sometimes I copy-paste stuff from past exams. The problems only looked at the structure, not the values — assume it's the same this time.

ALEX Comparing left and right — outer with outer, inner with inner, recursively. I know that function; I've implemented it in my head so many times.

Quantum · BogoSort

ALEX You mentioned quantum — will there be much?

PROF Something small — there will be a problem combining quantum computing and sorting. Do you remember BogoSort? You shuffle the dataset; if it's sorted by chance you're done, otherwise shuffle again. Obviously nonsense. Now think about what happens if you combine BogoSort with quantum computing. It's made up, not practical — more like a joke, a quantum BogoSort. That's all about quantum computing this year.

Closing · logistics & his final checklist

[aside — Math 2 retake went much better this time; SVD eigenspaces were the one gap; the professor: “make sure to get enough rest for tomorrow”]

PROF You know which room tomorrow? The exam is in several rooms — I'm proctoring in a different one, in the C building.

[Alex: reassigned on campus; room confirmed via email. Also: interest in the quantum computing course after results — “you'll hear from me once I have marked the exams.”]

PROF For tomorrow, remember which stuff is super important: graph definitions, hash tables — there are past examples of putting values in a hash table, drawing it, handling collisions by chaining. Then the trees: symmetric trees, decision trees. And for recursive functions — these Deggendorf numbers from past exams, and the lab problems video I shared. Something like this will also be very important for this year's exam.

ALEX Thank you so much.

PROF I wish you all the best, and I hope this session helped. And the stuff I told you — don't share it.

Call with Prof. Glauner, 19 Jul 2026 · auto-transcription, cleaned; attribution inferred; his key statements kept verbatim (bold). Actionable content distilled into the briefing and cheatsheet v3.PRIMARY SOURCE