如何找到带有标签的后代叶节点的最低祖先?

时间:2018-07-26 11:19:20

标签: algorithm data-structures tree ancestor lowest-common-ancestor

问题

给出具有 n 个节点的根树,其中所有叶子均从一组标签中进行标签。建立一个数据结构,给定一个叶节点 a 和一个标签 l ,可以找到 a中最低的祖先 u ,其中 u 至少有一个后代,标签为 l

线性空间/线性时间方法

  • 从叶子 a
  • 开始
  • 检查 a 的所有兄弟姐妹
    • 如果兄弟姐妹的标签为 l ,请找到 a 和该兄弟姐妹之间的最低共同祖先。
    • 否则继续作为父母
  • 如果未将所有来自父代的叶节点标记为 l ,请继续探访祖父母并检查其叶节点后代。
  • 继续递归检查祖父母及其所有后代叶子节点,直到找到标记为 l 的后代。

这具有时间复杂度 O(n)和空间复杂度 O(n)


有没有一种更快的方法来解决线性空间复杂性问题?也许通过某种方式对树进行预处理? l a 不固定,因此预处理必须灵活。

可以使用RMQ通过Eulerian-Tour在恒定时间内找到最低的共同祖先。

请记住,树不是以任何方式平衡或排序的。

2 个答案:

答案 0 :(得分:0)

这是具有 O(log(n)^ 3)时间复杂度和 O(n log(n))空间复杂度的解决方案。

String auftragsnummer;是您在欧拉路径上遇到的标签列表。您可以使用此列表构建一个细分树,然后在树的每个节点中存储出现在相应细分中的标签集。 然后,您可以通过段树中的范围查询,在 O(log(n)^ 2)时间中检查标签是否出现在子树中。

要找到正确的父母,可以进行二进制搜索。例如。类似于二进制提升。这将添加另一个因素 log(n)

答案 1 :(得分:0)

所以,现在我找到了一个更好的解决方案:

想法如下: 欧拉路径中出现的节点越多,其LCA越高。 即index(a) < index(b) < index(c) => dist_to_root(LCA(a, b)) >= dist_to_root(LCA(a, c))

这意味着您只需计算路径中标记为 l 的Lstrong和 a 的LCA以及 a 之后的第一个节点,以及 a 的LCA和 a 之前的最后一个节点,路径中带有标签 l

其中之一将为该问题提供最佳解决方案。

要有效地找到这两个索引,请为每个标签创建一个索引列表,然后在 O(log n)中执行二进制搜索。

内存复杂度为 O(n)