Algorithm Search⌘K

Proofs: Patience sorting

These are the human proofs of Patience sorting, at full length.

Patience sorting sorts stably, and its piles count the longest non-decreasing subsequence full

This proof shows: correctness.

We call a list of piles valid when each pile, read from the top down, is strictly increasing, and the tops are non-decreasing from left to right.

Lemma 1 (one deal step). If the piles are valid before line L3, they are valid after line L5, and line L3 finds the least index ii with x<top(P[i])x < \text{top}(P[i]).

Proof. The tops are non-decreasing, so the predicate "x<top(P[j])x < \text{top}(P[j])" is false for a prefix of the indices and true for the rest. A binary search for the first index where it is true is therefore correct, and returns ∣P∣|P| when it is true nowhere. If i<∣P∣i < |P|, the new top is x<top(P[i])x < \text{top}(P[i]), so the pile stays strictly increasing from the top. The left neighbour, if any, has top(P[i−1])≤x\text{top}(P[i-1]) \le x by the choice of ii, and the right neighbour has a top at least the old top of P[i]P[i], which is greater than xx. So the tops stay non-decreasing. If i=∣P∣i = |P|, the new pile holds only xx, and the last old top is at most xx. □\square

Theorem 1. PATIENCE-SORT(A)(A) writes the items of AA in non-decreasing order.

Proof. The empty list of piles is valid, so by Lemma 1 the piles are valid after the deal, and they hold each item once. During the merge, the item at the top of each pile is the least item of that pile. The heap root is a pile whose top is least among all tops, so line L8 outputs the least of the remaining items. By induction on tt, A[0…t]A[0 \ldots t] holds the t+1t + 1 least items in non-decreasing order. After nn steps all items are output. ■\blacksquare

Theorem 2 (stability). If yy and zz have equal keys and yy comes before zz in AA, then yy is output before zz.

Proof. Let yy be on pile pyp_y. When zz is dealt, the top of pyp_y is yy or an item placed on it later, which is less than yy; in both cases it is at most zz. The tops of the piles left of pyp_y are at most that top. So the binary search does not choose a pile with index at most pyp_y, and zz goes to a pile pz>pyp_z > p_y. In particular, two equal items never share a pile.

Suppose that zz is output while yy is still on its pile. Then zz is the top of pzp_z, and it is least among the tops. The top tt of pyp_y is yy or an item above yy; an item above yy is less than yy and so less than zz, which is impossible. So t=yt = y, the two tops are equal, and the heap breaks the tie for the lower index py<pzp_y < p_z. So yy is at the root, not zz. This is a contradiction. ■\blacksquare

Theorem 3 (the number of piles). The number kk of piles after the deal equals the length of the longest non-decreasing subsequence of AA.

Proof. Let yy come before zz with y≤zy \le z. When zz is dealt, the top of the pile of yy is at most y≤zy \le z, so as in Theorem 2, zz goes to a pile further right. So the items of a non-decreasing subsequence lie on piles with increasing indices, and its length is at most kk.

Conversely, when an item xx goes on pile i>0i > 0, let link(x)\text{link}(x) be the top of pile i−1i - 1 at that moment. By the choice of ii, link(x)≤x\text{link}(x) \le x, and it was dealt before xx. Start with any item of pile k−1k - 1 and follow the links k−1k - 1 times: each step goes to pile one to the left, to an item that comes earlier and is at most the current one. Read in reverse, these kk items form a non-decreasing subsequence. ■\blacksquare

Termination. The deal handles each item once, and each binary search halves its range. The merge removes one item in each of nn steps.

Back to Patience sorting