RANK and UNRANK are inverse bijections that respect lexicographic order full
This proof shows: correctness, termination.
We use the pseudocode of the page. Let Sn be the permutations of [n], and for a∈Sn let ci(a)=∣{j>i:aj<ai}∣ be its Lehmer code. Let Ui(a)=[n]∖{a1,…,ai−1} be the set of values not used before position i; it has n−i+1 elements and contains ai,…,an.
Lemma 1 (digits). ci(a)=∣{v∈Ui(a):v<ai}∣, and 0≤ci(a)≤n−i.
Proof. The values of Ui(a) other than ai are exactly ai+1,…,an, the values at the positions after i. So the values of Ui(a) below ai are the values after position i below ai. There are n−i positions after i. □
Lemma 2 (rank formula). rank(a):=∣{b∈Sn:b<a}∣=∑i=1nci(a)(n−i)!, where < is lexicographic order.
Proof. For b<a, let i be the first position with bi=ai; then bi<ai. So the set of b<a is the disjoint union over i of the sets Bi={b:b1⋯bi−1=a1⋯ai−1, bi<ai}. For b∈Bi, the value bi lies in Ui(a) and is below ai, which leaves ci(a) choices by Lemma 1, and then bi+1,…,bn is any order of the other n−i values of Ui(a), which leaves (n−i)! choices. Every such choice is a permutation in Bi. So ∣Bi∣=ci(a)(n−i)!. □
Lemma 3 (the Fenwick tree). If the tree T represents a 0-1 array f[1…n], then PREFIX(T,i) returns f[1]+⋯+f[i] and ADD(T,i,δ) makes T represent f with δ added to f[i]. This is the lemma proved on the Fenwick tree page: cell T[j] holds ∑j−lowbit(j)<v≤jf[v]. When every f[v]=1, cell j holds lowbit(j), so lines L1 and L8 build the tree of the all-ones array.
Lemma 4 (SELECT). Let T represent a 0-1 array f with F(p)=f[1]+⋯+f[p], and let 1≤k0≤F(n). Then SELECT(T,k0) returns the least q with F(q)≥k0, which is the k0-th smallest v with f[v]=1.
Proof. Let 2m be the initial value of s, the largest power of two with 2m≤n. We claim that before each test of line L14 with s=2t, three facts hold: p is a multiple of 2t+1 (for t=m, p=0), F(p)<k0 and k=k0−F(p), and the least q with F(q)≥k0 satisfies p<q≤p+2t+1, or p<q≤n when t=m. Initially p=0, F(0)=0<k0, k=k0, and q≤n<2m+1. In a round with s=2t, since p is a multiple of 2t+1, lowbit(p+s)=s, so by Lemma 3 the cell T[p+s] holds F(p+s)−F(p) when p+s≤n. The test T[p+s]<k is then F(p+s)<k0. If it holds, q>p+s, and the new p′=p+s has F(p′)<k0 and k′=k−T[p+s]=k0−F(p′). If it fails, or if p+s>n, then q≤p+s. In both cases the new p is a multiple of 2t and p<q≤p+2t (when p+s>n, q≤n<p+s). This is the claim for s=2t−1. When the loop ends after the round with s=1, p<q≤p+1, so q=p+1. Since f is 0-1 and F grows by 1 exactly at the values with f[v]=1, the least q with F(q)≥k0 is the k0-th such value. □
Theorem 1 (RANK). For a∈Sn, RANK(a) returns rank(a).
Proof. Invariant: before the iteration of line L2 with index i, T represents the indicator array of Ui(a), and r=Ri:=∑k<ick(a)∏t=k+1i−1(n−t+1). Before i=1, line L1 makes T the all-ones tree (Lemma 3), U1(a)=[n], and r=0=R1. In iteration i, line L3 sets c=∣{v∈Ui(a):v≤ai−1}∣=ci(a) by Lemmas 3 and 1. Line L4 removes ai, so T represents Ui+1(a). Line L5 sets
r=Ri(n−i+1)+ci(a)=k<i∑ck(a)t=k+1∏i(n−t+1)+ci(a)=Ri+1. After the last iteration, r=Rn+1=∑k=1nck(a)∏t=k+1n(n−t+1)=∑k=1nck(a)(n−k)!, which is rank(a) by Lemma 2. □
Theorem 2 (UNRANK). For 0≤r<n!, UNRANK(r,n) returns the a∈Sn with rank(a)=r.
Proof. Digits. Write r0=r, and let line L7 process i=n,n−1,…,1, with ρ the value of r before step i. At step i it sets di=ρmod(n−i+1) and replaces ρ by ⌊ρ/(n−i+1)⌋. By induction on the steps, before step i we have ρ=⌊r/∏t=i+1n(n−t+1)⌋=⌊r/(n−i)!⌋, and r=ρ(n−i)!+∑k>idk(n−k)! with 0≤dk≤n−k. After step 1, ρ=⌊r/n!⌋=0, so r=∑k=1ndk(n−k)! with 0≤dk≤n−k.
Items. Invariant: before the iteration of line L9 with index i, T represents the indicator array of Vi=[n]∖{a1,…,ai−1}, which has n−i+1 elements, and a1,…,ai−1 are distinct. Initially V1=[n] by line L8 and Lemma 3. In iteration i, 1≤di+1≤n−i+1=∣Vi∣, so by Lemma 4 line L10 sets ai to the (di+1)-th smallest element of Vi, which is new. Line L11 removes it, which gives Vi+1. At the end a1,…,an are n distinct values of [n], so a∈Sn, and Ui(a)=Vi for every i. By Lemma 1, ci(a) is the number of elements of Vi below ai, which is di. By Lemma 2, rank(a)=∑idi(n−i)!=r. The permutation is unique because rank is injective: by Lemma 2 it maps Sn into {0,…,n!−1}, and a<b implies rank(a)<rank(b), since every permutation below a is also below b and a itself is below b but not below a. □
Termination. The loops of lines L2, L7 and L9 run n times. The loop of PREFIX clears one set bit of i per round, the loop of ADD at least doubles lowbit(i) per round until i>n, and the loop of SELECT halves s until it is 0. So every loop ends, after at most ⌊lgn⌋+1 rounds for the three tree operations. ■