LCA算法(求两节点最近公共祖先)

最近公共祖先是指在有根树中,某两个节点u和v最近的公共祖先

祖先是指当前节点到树根的路径上所有的节点

LCA算法(求两节点最近公共祖先)_第1张图片

如果v本身是u的祖先,那么u和v的最近公共祖先就是v

比如G和B的最近公共祖先,B本身就是G的祖先,那么B就是G和B的最近公共祖先

-----------------------------------------------------------------------------------------------------------------------------

可以利用LCA求解树上任意两点之间的距离

LCA算法(求两节点最近公共祖先)_第2张图片

求解LCA的方法有很多,包括暴力搜索法,树上倍增法,在线RMQ算法 , 离线Tarjan算法

-------------------------------------------------------------------------------------------------------------------------

暴力搜索法

暴力搜索法有两种思路:

第一种是向上标记法:从u向上一直到根节点,标记所有经过的节点

此时如果v已经被标记,则v就是u和v的最近公共祖先节点

否则v也向上走,第一次遇到已标记的节点,该节点即为LCA(u,v)

LCA算法(求两节点最近公共祖先)_第3张图片

第二种是同步前进法:将u和v种深度较深的那个节点向上走到和深度较浅的节点同一深度,然后两个一起向上走,直到走到同一个节点,该节点就是u和v的最近公共最先

LCA算法(求两节点最近公共祖先)_第4张图片

如果较深的那个节点u到达和v同一深度时,那个节点正好就是v,那么v节点就是u和v的最近公共祖先节点

暴力搜索法求解LCA , 两种思路的时间复杂度最坏下均为O(n)时间

-------------------------------------------------------------------------------------------------------------------------------

树上倍增法

F[i ,j] 表示 i 的 2j 倍祖先,即 i  节点向根节点走2j 步到达的节点

LCA算法(求两节点最近公共祖先)_第5张图片

LCA算法(求两节点最近公共祖先)_第6张图片

然后利用ST 表,求解LCA

和前面暴搜中第二种同步前进法一样的,先让深度大的节点y向上走到与x同深度 , 然后x和y一起向上走,和爆搜不一样的是,向上走的按照倍增思想走的,不是一步一步地向上走,因此速度更快

怎么让深度大的节点y向上走到与x同深度呢??

总结:按照增量递减的方式,到达的节点深度比x的深度小时,什么也不做,到达的深度大于等于x深度时,y上移,直到增量为0,此时x,y在同一深度

LCA算法(求两节点最近公共祖先)_第7张图片

x和y一起向上走,怎么找到最难公共祖先节点呢??

假设x,y已经到达同一深度,现在一起向上走,假设k=3

1.x和y同时向上走2^3,到达是节点相同,什么也不做

2.减少增量,x,y同时向上走2^2步,此时到达的节点不同,x,y上移 x=F[x][2]  , y=F[y][2]

3.减少增量,x,y同时向上走2^1步,此时到达的节点不同,x,y上移 x=F[x][1]  , y=F[y][1]

4.减少增量,x,y同时向上走2^0步,此时到达的节点相同,什么也不做

总结:按照增量减少的方式,到达的节点相同时,什么也不做,到达的节点不同时,同时向上移,直到增量为0,此时,x,y的父节点即为公共祖先节点

LCA算法(求两节点最近公共祖先)_第8张图片

你可能感兴趣的:(数据结构高阶,数据结构)