Topics (384k) Articles (398k) Users (410) Discussions (242) Comments (383) Files (13k) New article
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Imperative programming 1 c Solution by
Codex 0 2026-10-31
Use missing-value search by deficient value intervals: halve the candidate value interval, and apply array partitioning only to the array segment whose entries lie in that interval.The loop invariant is , , andMore precisely, the segment contains all occurrences of original values in , and the complete array remains a permutation of its original state. The occurrences statement is essential: absence from the final segment must imply absence from the original array.
def missing(): Int = {
require(N < Int.MaxValue)
var lo = 0; var hi = N + 1
var l = 0; var r = N
while (hi - lo > 1) {
val p = lo + (hi - lo) / 2
val k = partition(l, r, p)
if (k - l < p - lo) {
hi = p; r = k
} else {
lo = p; l = k
}
}
lo
}After array partitioning, let , , , and . If , retain the left side. Otherwise the right side hasoccurrences. Either choice preserves the strict deficiency and the all-occurrences condition. The positive integer width decreases, proving termination. At width one, the active segment has fewer than one entry and is empty. ThereforeFor the time complexity, after splits the width is at most , and the scan length is smaller than that width. Summing over the levels gives a geometric series plus logarithmic overhead, hence overall, conventionally for . This proof bounds the retained occurrence count by the retained value width; it does not assume that each array partitioning splits the number of occurrences in half. The case returns zero immediately.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Imperative programming 1 a Solution by
Codex 0 2026-10-31
Maintain a processed prefix split into values below the pivot and values at least the pivot. The remaining suffix has not yet been classified. Here The loop invariant isIn addition, the active segment remains a permutation of its original contents, and every entry outside it remains unchanged. If
a and N are the given array and its length.def partition(l: Int, r: Int, p: Int): Int = {
require(0 <= l && l <= r && r <= N)
var k = l
var j = l
while (j < r) {
if (a(j) < p) {
val t = a(k); a(k) = a(j); a(j) = t
k += 1
}
j += 1
}
k
}a(j) < p, swapping it with a(k) extends the first region; the displaced entry, when the two positions differ, already belongs in the second region. Otherwise only the second region grows. The loop variant is . At termination , soThere are exactly iterations, giving time complexity and constant auxiliary space. Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 8 d Solution by
Codex 0 2026-10-31
Build a maximum spanning tree by the decreasing-weight version of Kruskal's algorithm. For the specified distinct endpoints , find their unique graph path in by depth-first search, retaining predecessors to reconstruct it. Return that path and its minimum edge weight .
For correctness, choose an edge of weight on . Deleting it splits into two connected components, separating from . No edge across this cut of a graph can have : replacing by would give a spanning tree of greater total weight, contradicting maximality of .
Every – graph path must cross the same cut of a graph, so it contains a crossing edge with . Therefore its minimum edge weight is at most . The tree route attains , provingThis is precisely the widest path problem. The proof allows tied, zero and negative edge weights. It depends on maximizing the total tree weight, not on a shortest-distance algorithm.
Let and . Sorting and Kruskal's algorithm take time; the tree search adds . HenceFor a connected simple graph with at least two vertices, , so the time is also . The expression remains valid when parallel edges are permitted. If the two endpoints coincide, the empty path is returned, with bottleneck under the usual empty-minimum convention; otherwise connectedness guarantees a nonempty route.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 8 c Solution by
Codex 0 2026-10-31
Run Kruskal's algorithm in nonincreasing order of edge weight, accepting an edge exactly when its endpoints belong to different current connected components. Use a disjoint-set data structure to test and merge those components. Stop after accepting edges.
Equivalently, apply ordinary Kruskal's algorithm to . For every spanning tree,so minimizing transformed total weight is exactly maximizing original total weight. Thus the output is a maximum spanning tree. Equal weights may be processed in any fixed order. Sorting dominates the time complexity, giving with the usual efficient disjoint-set data structure.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 8 b Solution by
Codex 0 2026-10-31
A precise safe-extension form of the cut lemma for minimum spanning trees is as follows. Let be contained in some minimum spanning tree. Let be a nonempty proper subset of , and suppose no edge of crosses the cut of a graph . If is any least-weight crossing edge, thenTo prove it, choose a minimum spanning tree containing . If , it already certifies the claim. Otherwise inserting creates a graph cycle. The other part of that graph cycle must cross the cut of a graph, so choose a crossing edge . It does not belong to , and . Then is a spanning tree containing , of weight no greater than the optimum. It is therefore also optimal.
With , a lightest crossing edge belongs to at least one minimum spanning tree. If that edge is uniquely lightest, it belongs to every minimum spanning tree, the strict version of the minimum spanning tree cut property. With ties, “every” would be false: in an equal-weight triangle either crossing edge can be omitted from some optimum.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 8 a Solution by
Codex 0 2026-10-31
For a finite connected graph with undirected edges and edge weights , a spanning tree is a connected, acyclic subgraph containing all vertices. It has edges. A minimum spanning tree is one minimizing the sum of its edge weights:It minimizes total weight, rather than the distance of every route from a chosen root. Equal edge weights may permit more than one minimum spanning tree; negative weights do not invalidate the definition.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 7 d Solution by
Codex 0 2026-10-31
Assume . Use bottom-up heap construction to make a max-heap of the first input items. For each subsequent input value , compare it with the root. If is at least the root, discard it; otherwise replace the root by and apply heapify down. Return the final root.
The loop invariant says the heap contains a multiset of the smallest values seen so far. It holds after initialization. If is at least the current largest retained value, the already retained items are no larger, so discarding preserves the invariant. If is smaller, remove one largest retained value and keep instead; precisely the smallest values remain. This argument handles equal integers by treating repeated occurrences as separate items. At the end,Construction costs ; each remaining value uses one comparison and at most one logarithmic repair. Thus the selection algorithm has time complexityFor , the heap is a single running minimum and the time is . The uniform expression covers that boundary; interpreting the printed literally at would incorrectly make it zero.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 7 c Solution by
Codex 0 2026-10-31
Count pairwise exchanges in the implementation from part (b), including the initial root/final-leaf exchange. For , the final leaf has a nonroot parent whose key is strictly larger than the leaf's key. That parent remains after deletion. If the moved leaf could stay at the root without a downward exchange, it would dominate both root children and hence every remaining descendant, contradicting that larger remaining parent. Thus at least one heapify down exchange is necessary.
One downward exchange suffices. The following level-order array is a max-heap on keys one through fifteen:Every parent is larger than both children. Exchange the root key fifteen with the final key ten, remove fifteen, then exchange ten with the larger root child fourteen. Ten now has children nine and eight, so repair stops. The final array is
Hence the best-case maximum deletion in a binary heap isThis best case can be arranged at any such size: make the root child on the opposite side from the old final leaf the largest remaining key, the old leaf smaller than its own ancestors but larger than all descendants of that opposite child, and fill the remaining positions in decreasing order along each branch. The promoted child then allows the leaf to stop at depth one.
For sizes two and three, one initial exchange can suffice; for size one no exchange between distinct positions is needed. If only exchanges during heapify down are counted, the answer for is one. In the fifteen-key example the two exchanges involve three distinct keys, namely fifteen, ten and fourteen. An implementation that moves a hole by assignments need not perform literal swaps, so the count is explicitly tied to the exchange implementation. The worst-case time complexity remains logarithmic even though this best-case repair is constant.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 7 b Solution by
Codex 0 2026-10-31
Store a complete binary tree in an array , with children and parent . The max-heap invariant says every parent's key is at least its children's keys. Consequently the root is a greatest-key item, and the height is .
Here is a pairwise-exchange implementation of
extractMax:extractMax(H, n):
if n == 0: error "empty priority queue"
answer = H[0]
swap(H[0], H[n-1])
n = n - 1
i = 0
while 2*i + 1 < n:
j = 2*i + 1
if j + 1 < n and key(H[j+1]) > key(H[j]):
j = j + 1
if key(H[i]) >= key(H[j]): break
swap(H[i], H[j])
i = j
return (answer, n)Only the root can initially violate heap order. Each heapify down exchange promotes the larger child, making the previous position valid and moving the only possible violation down one level. It either stops at a valid position or reaches a leaf. The removed root is saved as
answer, and reducing the active array length preserves the complete binary tree shape.| Operation | Worst-case time |
|---|---|
Empty initialization, isEmpty, size | |
maximum | |
insert, increaseKey | |
extractMax, deletion by handle | |
| Build from arbitrary items by bottom-up heap construction |
Insertion into the binary heap places an item at the next leaf and moves it upward until heap order holds. Raising a key uses the same upward repair. Arbitrary deletion replaces its position by the final item and repairs upward or downward as necessary. A handle must be updated on exchanges; locating an item by value alone can require linear search. The boxed main bounds are . Dynamic array resizing is usually amortized or avoided by reserving sufficient capacity.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 7 a Solution by
Codex 0 2026-10-31
A maximum priority queue is an abstract data type holding items with comparable priority keys and giving access to a greatest-key item. Equal priorities may occur; any one of the tied maximum items can be returned unless a tie rule is specified.
emptyor initialization creates a queue with no items;isEmptyandsizeinspect its occupancy.insert(item, key)adds an item with its priority.maximum()returns a greatest-priority item without removing it.extractMax()returns and removes a greatest-priority item.- When mutable priorities are supported,
increaseKey(handle, newKey)raises an existing item's priority; the handle identifies its stored location.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 6 e Solution by
Codex 0 2026-10-31
Store
pred[j] = i whenever a strict improvement sets D[j] = D[i] + 1. Initialize predecessors to NONE. After the dynamic programming pass, return NONE if the final position is unreachable; otherwise follow predecessors backwards:route = []
j = n - 1
while j != 0:
route.append(j)
j = pred[j]
route.append(0)
reverse(route)
return routeEvery stored predecessor is smaller than the current index, so reconstruction terminates. Its stored distance is exactly one smaller, so the output has precisely jumps and each jump satisfies its input bound. Therefore . Reconstruction takes additional time complexity and output space; the total dynamic programming bounds remain time and space complexity. Keeping the first predecessor on ties selects one optimal route deterministically.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 6 d Solution by
Codex 0 2026-10-31
Let be the minimum number of jumps from index zero to index , with denoting an unreachable position. The minimum forward-jump dynamic programming recurrence iswhere the minimum of an empty set is and . Compute it in increasing index order:
D[0] = 0
for j = 1, ..., n-1:
D[j] = INFINITY
for i = 0, ..., j-1:
if D[i] != INFINITY and A[i] >= j-i:
D[j] = min(D[j], D[i] + 1)
return D[n-1]For algorithm correctness, classify any route to by its penultimate index . Every jump advances, so , and legality requires . By the principle of optimality, a shortest prefix to can be used; this gives the lower bound represented by the recurrence. Conversely, a minimizing reachable predecessor supplies an actual route of length , proving attainability. Mathematical induction on therefore proves every stored value correct.
There are predecessor tests, and two arrays are unnecessary when only the number is required. ThusFor the source example, the computed array isWhen , zero jumps are needed even if the lone entry is zero. An unreachable final position returns . Testing
A[i] >= j-i also avoids forming a potentially overflowing sum i + A[i] in bounded implementations. A faster frontier-based algorithm is possible, but the displayed method directly supplies the requested dynamic programming solution. Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 6 c Solution by
Codex 0 2026-10-31
Dynamic programming solves related subproblems once, stores their results, and combines those results in an order consistent with their dependencies. The state must retain all information that determines the remaining choices and their costs. Here an adequate dynamic programming state is the current array index, since future jumps depend only on that index and the fixed input.
The principle of optimality says that the remaining part of an optimal solution must be optimal for the residual problem defined by its state. Equivalently here, the prefix ending at a particular intermediate position of a shortest route must be a shortest route to that position: replacing it by a shorter prefix would shorten the entire route. This is the optimal substructure needed by the dynamic programming recurrence.
Thus . Overlapping routes share states, so storing results avoids repeatedly solving the same subproblem.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 6 b Solution by
Codex 0 2026-10-31
After one jump, the largest reachable index is two. After at most two jumps, the reachable indices form the prefix : index two can reach five, but no reachable departure before that second jump can go further. From indices zero through five, the largest endpoint of one further jump is . Thus three jumps cannot reach index ten.
The two routesare valid and use four jumps. Therefore . The frontier argument proves the lower bound independently of merely exhibiting a route. In fact these are the two minimizing index sequences: the last departure in a four-jump solution must be eight or nine, reached in three jumps through four, which is reached in two jumps only through two.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 6 a Solution by
Codex 0 2026-10-31
Describe routes by array indices, so repeated entry values cannot confuse positions. Two valid routes areThe first uses jump lengths , bounded respectively by , , , . The second uses lengths , bounded by at its departing positions. Both reach the final index without landing at the zero entry at index six.
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 5 c Solution by
Codex 0 2026-10-31
Use the two-pointer technique, starting at opposite ends of the ordered sequence:
l = 0
r = n - 1
while l < r:
s = S[l] + S[r]
if s == x: return (l, r)
if s < x: l = l + 1
else: r = r - 1
return NONEIf the sum is too small, every remaining pair using
l has sum at most , so discard l. If the sum is too large, every remaining pair using r has sum at least , so discard r. The loop invariant says that every solution not already excluded has both indices in . These two elimination arguments preserve it; at termination fewer than two positions remain.Each unsuccessful iteration decreases by one. Therefore the two-sum problem is solved withThe condition
l < r ensures distinct positions and handles . Under the usual interpretation of “two distinct elements” as two different occurrences, equal values in different positions are allowed. If distinct numerical values are intended instead, reject an equality with : sortedness then makes the entire remaining interval equal, so it contains no distinct-value solution. Both interpretations retain linear time complexity. The comparison assumes exact real-number operations, as in the stated comparison model. Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 5 b Solution by
Codex 0 2026-10-31
The scan permits an arbitrary signed integer but prints . That expression is undefined for . The printed bound is proved below for positive ; for the stated signed domain the corresponding bound uses . This is a source qualification, rather than an unreadable part of the question.[ref]
Functional programming, design and analysis of algorithms examination paper by the University of Oxford (2014). p. 7, Question 5(b), printed logarithm and final absolute-value sentence
Choose a fixed positive integer with , and put . For positive , use coarse exponential bracketing: compare against until the first . Equality determines immediately. Otherwise, , except in the first interval where the lower bound is zero. Apply binary search to the remaining integer candidates.
There are at most bracketing comparisons and at most subsequent comparisons, because the interval width is at most . Minimality of gives . HenceThe additive constant may depend on the fixed , but is independent of . Taking larger jumps in the bracketing phase reduces its leading comparison cost; the overshoot costs only the fixed number of extra binary search levels.
For signed inputs, first compare with zero. If negative, set conceptually and perform the same search for : comparing with yields the reversed outcome of comparing with . Thus every test is still a permitted test of the sign of . Return zero immediately on equality in the initial test. The corrected all-input bound isAll thresholds are exact integers, generated by repeated multiplication by . Their arithmetic and storage costs are outside the requested comparison model; bounded machine arithmetic would not suffice for arbitrarily large .
Past exam of the year 1 of the computer science course of the University of Oxford 2014 Functional programming, design and analysis of algorithms 5 a Solution by
Codex 0 2026-10-31
Use binary search. Keep the half-open interval of candidate indices , initially . While it is nonempty, set and make one ternary comparison between the target and . Equality succeeds; a smaller target replaces by ; a larger target replaces by . An empty interval certifies absence.
The loop invariant is that every possible occurrence of lies in the current interval. Its preservation follows from the ordering of . After an unsuccessful comparison, at most candidates remain. Thus the maximum number of comparisons for satisfies with , givingOne ternary comparison supplies all three outcomes; it is not counted as separate less-than and equality tests. The comparison model abstracts away any cost of navigating a non-random-access sequence. For an array, navigation also takes constant time per step.
Pinned article: Introduction to the OurBigBook Project
Welcome to the OurBigBook Project! Our goal is to create the perfect publishing platform for STEM subjects, and get university-level students to write the best free STEM tutorials ever.
Everyone is welcome to create an account and play with the site: ourbigbook.com/go/register. We belive that students themselves can write amazing tutorials, but teachers are welcome too. You can write about anything you want, it doesn't have to be STEM or even educational. Silly test content is very welcome and you won't be penalized in any way. Just keep it legal!
Intro to OurBigBook
. Source. We have two killer features:
- topics: topics group articles by different users with the same title, e.g. here is the topic for the "Fundamental Theorem of Calculus" ourbigbook.com/go/topic/fundamental-theorem-of-calculusArticles of different users are sorted by upvote within each article page. This feature is a bit like:
- a Wikipedia where each user can have their own version of each article
- a Q&A website like Stack Overflow, where multiple people can give their views on a given topic, and the best ones are sorted by upvote. Except you don't need to wait for someone to ask first, and any topic goes, no matter how narrow or broad
This feature makes it possible for readers to find better explanations of any topic created by other writers. And it allows writers to create an explanation in a place that readers might actually find it.Figure 1. Screenshot of the "Derivative" topic page. View it live at: ourbigbook.com/go/topic/derivativeVideo 2. OurBigBook Web topics demo. Source. - local editing: you can store all your personal knowledge base content locally in a plaintext markup format that can be edited locally and published either:This way you can be sure that even if OurBigBook.com were to go down one day (which we have no plans to do as it is quite cheap to host!), your content will still be perfectly readable as a static site.
- to OurBigBook.com to get awesome multi-user features like topics and likes
- as HTML files to a static website, which you can host yourself for free on many external providers like GitHub Pages, and remain in full control
Figure 2. You can publish local OurBigBook lightweight markup files to either OurBigBook.com or as a static website.Figure 3. Visual Studio Code extension installation.Figure 5. . You can also edit articles on the Web editor without installing anything locally. Video 3. Edit locally and publish demo. Source. This shows editing OurBigBook Markup and publishing it using the Visual Studio Code extension. - Infinitely deep tables of contents:
All our software is open source and hosted at: github.com/ourbigbook/ourbigbook
Further documentation can be found at: docs.ourbigbook.com
Feel free to reach our to us for any help or suggestions: docs.ourbigbook.com/#contact






