TAOCP 3.4.2 Exercise 12
**Exercise 3.
Section 3.4.2: Random Sampling and Shuffling
Exercise 12. [**] [M36] The gist of Algorithm P is that any permutation $\pi$ can be uniquely written as a product of transpositions in the form $\pi = (a_1 t) \cdots (a_2 2)(a_1 2)$, where $1 \le a_j \le j$ for $1 \ge j > 1$. Prove that there is also a unique representation of the form $\pi = (b_t 2)(b_{t-1} 3) \cdots (b_1 t)$, where $1 \le b_j \le j$ for $1 < j \le t$, and design an algorithm that computes the $b$'s from the $a$'s in $O(t)$ steps.
Verified: no
Solve time: 4m34s
Exercise 3.4.2.12 [M36]
Solution.
We are asked to prove that if a permutation $\pi \in S_t$ is written in Algorithm P form
$$ \pi = (a_t, t) (a_{t-1}, t-1) \cdots (a_2, 2)(a_1,1), \quad 1 \le a_j \le j, $$
then $\pi$ also has a unique representation of the form
$$ \pi = (b_t,2)(b_{t-1},3)\cdots (b_1, t), \quad 1 \le b_j \le j, $$
and to give an $O(t)$-time algorithm to compute the $b$'s from the $a$'s.
We proceed in precise steps.
Step 1: Restate the original representation
By Algorithm P, any permutation $\pi \in S_t$ is uniquely represented as
$$ \pi = (a_t, t) (a_{t-1}, t-1) \cdots (a_2, 2) (a_1,1), $$
with $1 \le a_j \le j$. The factor $(a_1,1)$ is always trivial $(1,1)$, so we may ignore it. Then we have
$$ \pi = (a_t, t) (a_{t-1}, t-1) \cdots (a_2, 2). $$
Our goal is to rewrite this in the reverse-indexed form
$$ \pi = (b_t, 2)(b_{t-1}, 3)\cdots (b_2, t)(b_1,1), $$
or equivalently (ignoring $(b_1,1)$),
$$ \pi = (b_t,2)(b_{t-1},3)\cdots (b_2, t). $$
Notice that the factors now attach to positions $2,3,\dots,t$ in increasing order, with $b_j \le j$.
Step 2: Strategy for existence
The key observation is that Algorithm P defines a factorial-number representation of permutations: for each $j$, the transposition $(a_j,j)$ inserts the element $j$ into position $a_j$ in the growing permutation $[1,\dots,j]$.
Similarly, to produce the representation
$$ \pi = (b_t,2)(b_{t-1},3)\cdots (b_2,t), $$
we will insert each symbol $j$ at position $b_{t-j+2}$ in the partially constructed permutation, but now proceeding in reverse order. Concretely:
- Start with the identity permutation $\sigma_1 = [1]$.
- For $j = 2$ to $t$, define $b_{t-j+2}$ so that swapping positions $b_{t-j+2}$ and $j$ in the current sequence correctly inserts $j$ at its position according to the permutation $\pi$.
Equivalently, we can view the mapping from $a$-indices to $b$-indices as reindexing the factorial representation in reverse.
Step 3: Inductive construction
Let us define the sequence $(b_2,\dots,b_t)$ inductively. Let $\pi^{(j)} = (a_j, j) (a_{j-1}, j-1) \cdots (a_2,2)$ denote the partial product of the first $j-1$ factors from the original Algorithm P form. We want
$$ \pi^{(j)} = (b_j,2)(b_{j-1},3)\cdots (b_2, j). $$
Then $b_j$ is determined as follows:
$$ b_j = \text{the image of } j \text{ under the inverse of the partial product of the previous } b\text{-transpositions}. $$
Formally, if we let
$$ \beta_{j-1} = (b_{j-1},2)(b_{j-2},3)\cdots (b_2, j-1), $$
then define
$$ b_j = \beta_{j-1}^{-1}(j). $$
This guarantees that
$$ (b_j, j) \beta_{j-1} = \pi^{(j)}. $$
Hence by induction, each $b_j$ is uniquely determined, and existence is established.
Step 4: Uniqueness
To prove uniqueness, observe:
- The final transposition $(b_t,2)$ moves $t$ to its position in $\pi$. Since positions are distinct, $b_t$ is uniquely determined.
- Once $b_t$ is fixed, the next transposition $(b_{t-1},3)$ must move $t-1$ to its position in the partial permutation. Again, $b_{t-1}$ is uniquely determined.
- Proceeding inductively, each $b_j$ is uniquely determined by $\pi$.
Therefore the representation
$$ \pi = (b_t,2)(b_{t-1},3)\cdots (b_2, t) $$
is unique.
Step 5: Algorithm to compute $b_j$ from $a_j$
We can compute the $b$'s in $O(t)$ steps using an array $p[1..t]$ representing the current permutation of positions.
Idea: Let $p[k]$ track the element currently at position $k$. Initially, $p[k] = k$. Each transposition $(x,y)$ swaps $p[x]$ and $p[y]$.
Algorithm:
Input: a[2..t] # Algorithm P indices
Output: b[2..t] # Reindexed representation
# Initialize identity permutation
for i = 1 to t:
p[i] = i
# Compute b-values in increasing j
for j = 2 to t:
# Find position of j in current partial permutation
for k = 2 to j:
if p[k] == j:
b[j] = k
break
# Swap to apply the transposition (b[j] j)
swap p[b[j]] and p[j]
Explanation:
- At iteration $j$, $p$ represents the partial permutation constructed so far from the $b$-transpositions.
- $b[j]$ is chosen so that $(b[j],j)$ moves $j$ to its correct position according to $\pi$.
- Swapping $p[b[j]]$ and $p[j]$ updates $p$ to include the new transposition.
Each outer iteration performs $O(1)$ work if we maintain positions in a separate array for constant-time lookup. Therefore, the total complexity is $O(t)$.
Step 6: Summary
- Existence: Define $b_j = \beta_{j-1}^{-1}(j)$, where $\beta_{j-1}$ is the partial product of previous $b$-transpositions.
- Uniqueness: Each $b_j$ is uniquely determined from $\pi$ by induction on $j$.
- Algorithm: Maintain a permutation array to compute $b_j$ and update by swapping, yielding an $O(t)$-time procedure.
This completes the solution.
∎
Pseudocode (compact $O(t)$ version with position array for constant-time lookup):
Input: a[2..t]
Output: b[2..t]
# Initialize identity permutation and inverse position array
for i = 1 to t:
p[i] = i
pos[i] = i
for j = 2 to t:
b[j] = pos[j] # position of j in current permutation
swap p[b[j]] and p[j] # apply transposition (b[j] j)
pos[p[b[j]]] = b[j] # update position of swapped element
pos[p[j]] = j
This correctly computes the unique sequence $(b_2,\dots,b_t)$ corresponding to the permutation $\pi$ represented by $(a_2,\dots,a_t)$.