哪种算法最适合在树中查找 LCA?

Posted

技术标签:

【中文标题】哪种算法最适合在树中查找 LCA?【英文标题】:Which algorithm is best to use for finding LCA in tree? 【发布时间】:2021-12-20 14:03:57 【问题描述】:

我有兴趣以尽可能低的复杂性找到树中两个节点的距离。查找过程是在树上的一些查询和更新(添加和删除一个节点)。

这个问题可以使用 LCA 作为优化工具。但是,通过我发现的这些帖子,有一些可用的算法。

https://cp-algorithms.com/graph/lca.html https://cp-algorithms.com/graph/lca_binary_lifting.html

这里是总结,

    LCA + Sqrt 分解

预处理时间:O(N)

查询时间:O(√N)

允许更新树:是

    LCA + 段树

预处理时间:O(N)

查询时间:O(log N)

允许更新树:是

    LCA + 稀疏表

预处理时间:O(N log N)

查询时间:O(1)

允许更新树:

    LCA + 二元提升

预处理时间:O(N log N)

查询时间:O(log N)

允许更新树:是

我的问题是,最好使用什么算法?

或者在什么条件下使用哪种算法最好?

每种算法是否还有其他没有在上面提到的优点或缺点?

【问题讨论】:

【参考方案1】:

作为有竞争力的程序员的个人经验:

LCA + Sqrt 分解 - 从未使用过这个,查询时间似乎很慢 LCA + Segment Tree - 这个非常好,唯一的缺点是代码有点乏味 - 我很少使用它,通常用于已经需要 Segment Tree 的一些问题(即重轻分解) LCA + 稀疏表 - O(1) 查询时间对于某些问题来说是必须的,即使它们可能很少见 LCA + 二元提升 - 我 90% 的时间都在使用它 - 易于编码且速度非常快

【讨论】:

OK 让我们用 sqrt 分解删除一个,因为它速度慢,用稀疏表删除一个,因为如果树上有更新,我们必须更新整个表。剩下的(segment tree 或者二叉提升),猜猜最好用一个segment tree,因为预处理时间比较快?还是有其他隐藏的优点或缺点?

以上是关于哪种算法最适合在树中查找 LCA?的主要内容,如果未能解决你的问题,请参考以下文章

在树中的递归查找

第五十三课 树中节点的查找操作

设计一个算法,计算出给定二叉树中任意2 个结点之间的最短路径。

最近公共祖先 LCA 递归非递归

数据结构(C语言版) 查找 算法设计Demo4

如何使用广度优先搜索在树中找到从一个顶点到另一个顶点的路径?