Algorithm Search⌘K

Proofs: Cartesian tree

These are the human proofs of Cartesian tree, at full length.

The stack build gives the Cartesian tree, and range minima are lowest common ancestors full

This proof shows: correctness, termination.

Let A[0..n−1]A[0..n-1] be an array over a totally ordered set. Compare positions by the pairs (A[i],i)(A[i], i), which are distinct; "the minimum of a range" means the position with the least pair, which is the leftmost minimum of the values. For 0≤a≤b≤n−10 \le a \le b \le n - 1 let C(a,b)C(a, b) be the binary tree on the positions a,…,ba, \ldots, b defined by: the root is the minimum mm of [a,b][a, b], the left subtree is C(a,m−1)C(a, m - 1) and the right subtree is C(m+1,b)C(m + 1, b), where C(a,a−1)C(a, a - 1) is empty. The Cartesian tree of AA is C(0,n−1)C(0, n - 1).

Lemma 1 (characterization). A binary tree on the positions a,…,ba, \ldots, b is C(a,b)C(a, b) if and only if (1) its inorder is a,a+1,…,ba, a + 1, \ldots, b and (2) every node has a smaller pair than each of its descendants.

Proof. C(a,b)C(a, b) has both properties, by induction on b−ab - a: the inorder is In(C(a,m−1))⋅(m)⋅In(C(m+1,b))In(C(a, m-1)) \cdot (m) \cdot In(C(m+1, b)), and mm has the least pair in [a,b][a, b]. Conversely, let TT have both properties and root xx. By (2), xx has the least pair, so x=mx = m. By (1), the left subtree holds exactly the positions before mm in inorder, a,…,m−1a, \ldots, m - 1, and has both properties, so by induction it is C(a,m−1)C(a, m - 1); the same holds on the right. □\square

Lemma 2 (subtrees are ranges). In C(0,n−1)C(0, n-1) the subtree of each node xx is a range [lo(x),hi(x)][lo(x), hi(x)] of positions, and xx is its minimum.

Proof. By the recursive definition, each subtree is some C(a,b)C(a, b), whose node set is [a,b][a, b] and whose root is the minimum of [a,b][a, b]. □\square

Lemma 3 (the spine). In C(0,i)C(0, i) the right spine, the path from the root that always takes the right child, consists of the positions ss such that (A[s],s)<(A[t],t)(A[s], s) < (A[t], t) for all tt with s<t≤is < t \le i, in increasing order of position and of pair.

Proof. The spine of C(a,b)C(a, b) is the root mm followed by the spine of C(m+1,b)C(m + 1, b). By induction on b−ab - a, its nodes are mm and the positions of [m+1,b][m + 1, b] that beat every later position in [m+1,b][m+1, b]. A position s<ms < m is not on the spine and is beaten by mm, which is later. The position mm beats everything after it. A position s>ms > m beats every later position of [m+1,b][m+1, b], which is all of its later positions. So the spine is as stated. □\square

Lemma 4 (one round). Suppose that before round ii (lines L3 to L8) the arrays parentparent, leftleft, rightright restricted to the positions 0,…,i−10, \ldots, i - 1 describe C(0,i−1)C(0, i - 1), and the stack SS holds its right spine with the root at the bottom. Then after the round they describe C(0,i)C(0, i), and SS holds its right spine.

Proof. Let the spine be s1,…,sks_1, \ldots, s_k, bottom to top. By Lemma 3 the pairs increase along it. Line L4 compares A[sk]>A[i]A[s_k] > A[i], which, since sk<is_k < i, is the same as (A[sk],sk)>(A[i],i)(A[s_k], s_k) > (A[i], i). The loop pops the spine nodes with a larger pair than ii; they form a top segment sq+1,…,sks_{q+1}, \ldots, s_k, because the pairs increase. Afterwards last=sq+1last = s_{q+1} (or NIL if nothing was popped), and the top is sqs_q (or the stack is empty if q=0q = 0).

Consider the tree TT produced by lines L6 and L7: ii becomes the right child of sqs_q, replacing sq+1s_{q+1}, and sq+1s_{q+1} with its whole subtree becomes the left child of ii; ii has no right child. If q=0q = 0, ii is the root and the whole old tree is its left subtree.

Check property (1) of Lemma 1. The old right subtree of sqs_q was the range [sq+1,i−1][s_q + 1, i - 1], the end of the inorder. Now the right subtree of sqs_q is ii with that range as its left subtree, so the inorder is the old one followed by ii. Check property (2). The ancestors of ii are s1,…,sqs_1, \ldots, s_q, all with smaller pairs. The descendants of ii are the subtree of sq+1s_{q+1}, the range [sq+1,i−1][s_{q+1}, i - 1]; its minimum is sq+1s_{q+1} by Lemma 2, and sq+1s_{q+1} has a larger pair than ii. All other ancestor relations are as before, except that ii was inserted between sqs_q and sq+1s_{q+1}, and sq<i<sq+1s_q < i < s_{q+1} in pairs. So by Lemma 1, T=C(0,i)T = C(0, i).

Line L8 pushes ii, so the stack is s1,…,sq,is_1, \ldots, s_q, i. In TT the spine goes from the root along s1,…,sqs_1, \ldots, s_q, then to the right child ii of sqs_q, which has no right child. So the stack holds the spine of C(0,i)C(0, i). □\square

Termination and the result. Before round 0 the tree and the stack are empty, which describes C(0,−1)C(0, -1). By Lemma 4 and induction on ii, after round n−1n - 1 the arrays describe C(0,n−1)C(0, n - 1), and the bottom of the stack is its root, which line L9 returns. Every round ends, because the loop of line L4 pops a node each time and the stack is finite; each position is pushed exactly once, so there are at most nn pops in all.

Lemma 5 (range minimum). For 0≤i≤j≤n−10 \le i \le j \le n - 1, the minimum of [i,j][i, j] is lca(i,j)\mathrm{lca}(i, j) in C(0,n−1)C(0, n - 1).

Proof. Let x=lca(i,j)x = \mathrm{lca}(i, j). By Lemma 2 the subtree of xx is a range that contains ii and jj, so it contains [i,j][i, j], and xx is the minimum of that range. If xx were outside [i,j][i, j], say x<ix < i, then ii and jj would both be in the right subtree of xx by property (1), and the right child of xx would be a deeper common ancestor. The case x>jx > j is the same with the left subtree. So x∈[i,j]x \in [i, j], and as the minimum of a range that contains [i,j][i, j], it is the minimum of [i,j][i, j]. ■\blacksquare

Back to Cartesian tree