Solution

ID: past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2017/imperative-programming/2/e/solution

Each recursive call is a tail call: nothing remains to be computed after it returns. Replace it by an update of the retained bounds:
function Select(i; var a; N): T
    require 1 <= i <= N
    target := i-1
    l := 0
    r := N
    while true do
        Partition(a,l,r,m,n)
        if target < m then
            r := m
        else if target >= n then
            l := n
        else
            return a[target]
The loop invariant retains the target order statistic in with . Each nonreturning iteration strictly decreases , because is nonempty. This proves termination and replaces recursive stack space by auxiliary space, apart from the pivot routine's own storage.

New to topics? Read the docs here!