深入理解RMQ & LCA
正文
第一节 RMQ、LCA概述
LCA:Lowest Common Ancestor,译为最近公共祖先。其解释就是说:在有根树中,找出树中任意两个节点最近的公共祖先,或者说找到任意两个节点离树根最远的公共祖先。
RMQ:Range Minimum Query,译为区间最小值查询。其解释就是说:对于含有N个元素的数列A,在数列中找到两个指定索引之间的最小值及最小值的位置。
第二节 RMQ Algorithm
首先我们来看RQM算法,我将会根据预处理和查询的速度介绍几种解决该问题的方法。
设有数组A[N],其表示如下:
要求求得区间(2,7)的最小元素,如下图所示:
解法一:直接遍历区间
看到这个问题之后,我们最先想到的就是对区间的这些数进行一次遍历,就可以找到区间的最值,因此查询的时间为O(M)。但是,当数据量非常大并且查询很频繁时,直接遍历序列的效果就不是那么理想了。因为每查询一次就得对序列做一次遍历,对于大数据量这显然不能满足要求了。不过对于小数据量,这种算法倒是不错的选择!
查询:O(M)。
算法的代码如下:
int MaxNum = 0;
for(i = 0; i < range; i++)
{
/**查找最大值**/
if(array[i] > MaxNum)
{
MaxNum = array[i];
}
}
解法二:切割法
解法一中查询的速度为O(M),如果每次查询都这样的话,那真就成了龟速了。于是我们对解法一做了预处理,这就是该节要讲的:切割法。
首先,我们将序列分成sqrt(N)个部分,用数组M[sqrt(N) ]来表示每个部分中最小的值的下标,即这个最小数的位置。对于数组M,我们只需对原序列进行一次遍历就可以得到M。如下图所示:
接下来我们来求RMQ[2,7]。为了得到区间[2,7]的最小值,我们需比较