Solution (source code)

= 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 $[l,r)$ with $l\leq target<r$. Each nonreturning iteration strictly decreases $r-l$, because $[m,n)$ is nonempty. This proves termination and replaces recursive stack space by \b[$O(1)$ auxiliary space], apart from the pivot routine's own storage.