Crates.io | cartesian-tree |
lib.rs | cartesian-tree |
version | 0.1.0 |
source | src |
created_at | 2022-09-28 19:03:48.376621 |
updated_at | 2022-09-28 19:03:48.376621 |
description | Construct a Cartesian Tree from a Slice in Linear Time |
homepage | https://github.com/jlikhuva/blog/blob/main/posts/mathematical-sciences/rmq.md#cartesian-trees--the-lca-rmq-equivalence |
repository | https://github.com/jlikhuva/k2m2/tree/main/cartesian-tree |
max_upload_size | |
id | 676001 |
size | 14,937 |
Convert any array into a Cartesian Tree in Linear Time.
A cartesian tree is a derivative data structure. It is derived from an underlying array.
More formally, the cartesian tree T
of an array A
is a min binary heap of the elements of A
organized such that an in order traversal of the tree yields the original array.
To construct a cartesian tree from an underlying array, we are guided by the following:
Why are cartesian trees important? They are quite useful when solving the Range Min Query
problem: given a cartesian tree for an array, we can answer any RMQ on that array. In particular, $RMQ_A(o, j) = LCA_T(A[i], A[j])$. That is we can answer RMQ by doing lowest common ancestor searches in the cartesian tree. See here for more details.
We build the cartesian tree incrementally -- adding in elements in the order that they appear in the array. To add an element X
, we inspect the right spine of the tree starting with the right most node. We follow parent pointers until we find an element, Y
, in the tree that is smaller than X
. We the modify the tree, making X
a right child of Y
. We also make the rest of the right subtree that is below X
a left subtree of the new node.
Traversing the right spine of tree from the right-most node can be done efficiently by keeping nodes on the right spine in a stack. That way, the rightmost node is always at the top of the stack.
When do two cartesian trees for two different arrays, A
and B
, have the same shape? How can we tell this efficiently?
Put simply, if two arrays have the same cartesian tree shape, then the minimal values, in any range, in both arrays occur at the same index. This means that, the sequence of Push
and Pop
operations when constructing the cartesian trees for the two arrays are exactly the same. Therefore, to know if two arrays are isomorphic, we could simply compare the operations needed to construct each tree.
As an aside, when we are only interested in whether two arrays have isomorphic trees, we don't even need to construct the tree. We can instead create a bit-string from the sequence of Push
and Pop
operations. The number formed by this bit-string is called the cartesian tree number
. Therefore, with this scheme, two arrays have isomorphic trees if they have the same cartesian tree number.