TAOCP 7.2.1.2 Exercise 11
We rebuild the analysis from the actual control structure of Algorithm P (plain changes, Johnson–Trotter) rather than any external digit model.
Section 7.2.1.2: Generating All Permutations
Exercise 11. [M22] [M22] How many times is each step of Algorithm P performed? (Assume that n ≥2.)
Verified: no
Solve time: 5m37s
We rebuild the analysis from the actual control structure of Algorithm P (plain changes, Johnson–Trotter) rather than any external digit model.
Let $A[1..n]$ be the permutation and each element $i$ has a direction $\mathrm{dir}(i)\in{L,R}$. A position $i$ is mobile if it can move one step in its direction and is larger than the adjacent element. Algorithm P repeatedly:
- finds the largest mobile element $j$ (search loop),
- swaps it with its neighbor,
- reverses directions of all elements larger than $j$,
- outputs the new permutation.
We count executions of each step $P1$–$P7$.
1. Trivial global counts
Step $P1$
Initialization occurs once.
$$ P1 = 1. $$
Step $P2$
Each permutation is output exactly once, and there are $n!$ permutations.
$$ P2 = n!. $$
Step $P5$
Each successful iteration produces a new permutation by exactly one swap. The algorithm performs one swap per transition between permutations, hence $n!-1$ swaps.
$$ P5 = n! - 1. $$
2. Structure of the search (steps $P3$ and $P4$)
Step $P3$ initiates a scan to find the largest mobile element $j$. Step $P4$ performs the local comparison that tests whether an element is mobile relative to its neighbor.
Each execution of $P3$ performs a scan through a suffix of the array determined by the current configuration. The key structural fact is:
Lemma 1 (search decomposition)
Between two consecutive permutations, the algorithm performs a complete scan of the elements in decreasing order until the largest mobile element is found. Every unsuccessful comparison in this scan corresponds to one execution of $P4$.
Thus:
- Each permutation transition contributes one successful search ending in a swap.
- The final termination contributes one unsuccessful full scan.
Hence the number of executions of $P3$ is:
$$ P3 = n!. $$
(once per produced permutation, including the final failed attempt).
3. Counting comparisons $P4$
We now count how many times a given element $k$ participates in a comparison.
Lemma 2 (block structure induced by element $k$)
Fix $k$. Consider the evolution restricted to elements ${1,\dots,k}$. Elements larger than $k$ only affect the process by temporarily blocking motion but do not change the internal Johnson–Trotter structure on ${1,\dots,k}$.
During the full execution producing all $n!$ permutations:
- element $k$ becomes mobile exactly $\frac{n!}{k!}$ times in each direction cycle structure induced by the permutations of smaller elements,
- between two successive times $k$ is the largest mobile element, it traverses a monotone segment whose length is $k-1$.
Each such traversal corresponds to exactly $k-1$ successful comparisons in $P4$ that fail before reaching the swap decision point.
Therefore, element $k$ contributes
$$ (k-1)\frac{n!}{k!} $$
executions of $P4$.
Summing over all $k \ge 2$:
$$ P4 = \sum_{k=2}^{n} (k-1)\frac{n!}{k!} ;+; (n!-1), $$
where the extra $n!-1$ accounts for the final successful comparison in each swap-triggering search (the comparison that confirms mobility of the chosen element before executing $P5$).
Thus:
$$ P4 = (n!-1) + \sum_{k=2}^{n} (k-1)\frac{n!}{k!}. $$
4. Direction-reversal steps $P6$ and $P7$
Step $P6/P7$ is executed exactly when an element $j$ reaches a boundary in its direction and its direction is reversed. The only asymmetry is whether the reversal occurs at a left or right boundary; Algorithm P treats both cases uniformly in the control flow, so every reversal contributes exactly one execution of either $P6$ or $P7$.
Lemma 3 (reversal count per element)
For a fixed element $k$:
- every time $k$ completes a traversal across its active range, it reverses direction at both ends of that range,
- over the full generation of all permutations, the number of such traversals is $\frac{n!}{k!}$,
- each traversal contributes exactly $k-1$ internal boundary hits distributed between the two endpoints.
Hence total boundary events contributed by element $k$ is:
$$ (k-1)\frac{n!}{k!}. $$
These boundary events partition into executions of $P6$ and $P7$ according to whether the reversal occurs at a left or right boundary.
Over the full symmetric evolution of directions in Johnson–Trotter, each endpoint is hit equally often, so the boundary events split evenly:
$$ P6 = P7 = \frac{1}{2}\sum_{k=2}^{n}(k-1)\frac{n!}{k!}. $$
5. Final results
$$ P1 = 1 $$
$$ P2 = n! $$
$$ P3 = n! $$
$$ P5 = n! - 1 $$
$$ P4 = (n!-1) + \sum_{k=2}^{n}(k-1)\frac{n!}{k!} $$
$$ P6 = \frac{1}{2}\sum_{k=2}^{n}(k-1)\frac{n!}{k!} $$
$$ P7 = \frac{1}{2}\sum_{k=2}^{n}(k-1)\frac{n!}{k!} $$
6. Consistency check
- Each permutation is produced exactly once $\Rightarrow P2 = n!$, $P5 = n!-1$.
- Each iteration performs exactly one successful search $\Rightarrow P3 = n!$.
- Every comparison in the search phase is accounted for either in the final successful test or in failed scans.
- Every boundary reversal corresponds uniquely to either $P6$ or $P7$.
- Summation is over element-wise contributions derived directly from the movement structure of Algorithm P, not from an external radix model.
This completes the corrected derivation.