Shuffling 52 Cards So Every Order Is Equally Likely

Coding · Medium · Free problem

You have a deck of $52$ cards and a random number generator that produces uniform random numbers. Design an algorithm that shuffles the deck so that every one of the $52!$ orderings is equally likely. Analyze the running time, and prove that your algorithm is uniform.

Also explain why the following "obvious" method is wrong: for $i = 1, \dots, n$, swap card $i$ with a card chosen uniformly at random from all $n$ positions.

Hints

  1. One correct method: attach an independent uniform random key to every card and sort by key. Why is every order equally likely, and what does the sort cost?
  2. A faster method (Fisher-Yates / Knuth shuffle): for $i = 1, \dots, n-1$, pick $j$ uniformly from $\{i, \dots, n\}$ and swap positions $i$ and $j$. Position $i$ then holds a uniformly random choice among the cards not yet placed.
  3. Count outcomes for the wrong method: it has $n^n$ equally likely execution paths but must land on $n!$ orderings, and $n^n$ is not divisible by $n!$ for $n > 2$, so the orderings cannot be equally likely.

Worked Solution

How to Think About It: A uniform shuffle must give each of the $n!$ orders probability exactly $1/n!$. Think of building the order sequentially: if each slot is filled by a uniform choice among the remaining cards, the probabilities multiply to $1/n!$. The alternative is to reduce shuffling to sorting random keys, which is uniform because i.i.d. continuous keys are equally likely to come out in any order.

Approach: Present both correct methods, prove uniformity by induction or by the product rule, then show the naive method fails by a counting (divisibility) argument.

Formal Solution:

Method 1 -- Random keys and sort. Draw $n$ i.i.d. $U(0,1)$ keys $u_1, \dots, u_n$, attach $u_k$ to card $k$, and sort the cards by key. With probability $1$ the keys are distinct, and by exchangeability every one of the $n!$ relative orderings of $(u_1, \dots, u_n)$ has the same probability, so each deck order has probability $1/n!$. Cost: $n$ random numbers plus a sort, $\Theta(n\log n)$ time and $\Theta(n)$ space.

Method 2 -- Fisher-Yates / Knuth shuffle.

```python import random def knuth_shuffle(a): n = len(a) for i in range(n - 1): # positions 0 .. n-2 j = random.randrange(i, n) # uniform over i .. n-1 (inclusive) a[i], a[j] = a[j], a[i] return a ```

*Uniformity, product argument.* After step $i$, position $i$ holds a card chosen uniformly among the $n - i$ cards that were still in positions $i, \dots, n-1$ (0-indexed), independently of the earlier choices. For any target order $(c_0, c_1, \dots, c_{n-1})$, the probability that step $0$ places $c_0$ is $1/n$, that step $1$ then places $c_1$ is $1/(n-1)$, and so on, giving $\prod_{k=0}^{n-1}\frac{1}{n-k} = \frac{1}{n!}$.

*Uniformity, induction.* Claim: after processing position $i$, the multiset in positions $i+1, \dots, n-1$ is the set of unplaced cards, and the prefix $(a_0, \dots, a_i)$ is a uniformly random ordered selection of $i+1$ cards (each of the $n(n-1)\cdots(n-i)$ possibilities has equal probability). Base case $i = 0$: $a_0$ is uniform over $n$ cards. Step: given any prefix of length $i$, step $i$ appends each remaining card with probability $1/(n-i)$, so every prefix of length $i+1$ has probability $\frac{1}{n(n-1)\cdots(n-i)}$. At $i = n-1$ this is $1/n!$.

*Cost.* $n - 1$ random numbers and swaps: $\Theta(n)$ time, $O(1)$ extra space, in place.

Why the naive method is biased. The procedure "for $i = 1..n$ swap card $i$ with a uniformly random position in $1..n$" makes $n$ independent choices with $n$ options each, so it has $n^n$ equally likely execution paths. These paths map onto $n!$ orderings, and each ordering's probability is (number of paths producing it)$/n^n$. For uniformity every ordering would need exactly $n^n/n!$ paths, but $n!$ does not divide $n^n$ for $n \ge 3$ (for example $27/6$ is not an integer), so uniformity is impossible. Concretely, for $n = 3$ the orders $(1,2,3)$, $(3,1,2)$, $(3,2,1)$ each get probability $4/27$, and $(1,3,2)$, $(2,1,3)$, $(2,3,1)$ get $5/27$ (enumerate the $27$ paths to check). A simulation of $600{,}000$ shuffles of four cards gave chi-square statistics of $20$ (Knuth, consistent with uniform on $23$ degrees of freedom) versus $18{,}000$ (naive).

Answer: Fisher-Yates / Knuth shuffle: for $i = 1, \dots, n-1$ swap $A[i]$ with $A[j]$ where $j$ is uniform on $\{i, \dots, n\}$; each order has probability $\frac1n\cdot\frac1{n-1}\cdots\frac11 = \frac{1}{n!}$, in $\Theta(n)$ time and $O(1)$ space. Alternatively assign i.i.d. uniform keys and sort, $\Theta(n\log n)$. Swapping each position with a uniformly random position among all $n$ is biased because $n!$ does not divide $n^n$.

Intuition

The Knuth shuffle builds the permutation one slot at a time: slot $i$ receives a card chosen uniformly from the cards not yet placed, so a specific final order has probability $\tfrac1n \cdot \tfrac{1}{n-1} \cdots \tfrac11 = 1/n!$. The naive "swap with any position" version feels equally random but generates $n^n$ equally likely paths, and since $n!$ does not divide $n^n$, some orders must be hit more often than others (for $n = 3$ the bias is already $\tfrac{4}{27}$ versus $\tfrac{5}{27}$). Uniform shuffling is the primitive behind permutation tests, bootstrap resampling of trades, and randomized order assignment in simulations, so a biased shuffle silently corrupts every downstream p-value.

Open the full interactive solver →