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

Posted

技术标签:

【中文标题】如何找到具有某个标签的后代叶节点的最低祖先?【英文标题】:How does one find the lowest ancestor with a descendant leaf node with some label? 【发布时间】:2018-07-26 11:19:20 【问题描述】:

问题

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

线性空间/线性时间方法

从叶 a 开始 检查 a 的所有兄弟姐妹 如果兄弟姐妹有标签 l,则查找 a 和该兄弟姐妹之间的最低共同祖先。 否则继续父母 如果所有从父母传下来的叶节点都没有标记为 l,则继续到祖父母并检查他们的叶节点后代。 继续递归检查大祖父母及其所有后代叶节点,直到找到标记为 l 的后代。

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


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

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

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

【问题讨论】:

如果al 是兄弟姐妹,那么根据定义它们共享同一个父节点,即最低的共同祖先。 a 的“兄弟姐妹”在这里是什么意思?另外,你的节点有父指针吗? @JimMischel 是的,如果 a 和标签为 l 的某个节点是兄弟节点,那么是的,父节点将是最低的共同祖先。我只是使用“较低的共同祖先”,以便它适用于任何两个叶节点。 如果您愿意在预处理上花费时间和内存,您可以创建一个查找表,为您提供 O(1) 查询。内存需求为 O(m^2),其中 m 是叶节点的数量。 是的,但是该算法适用于没有额外数据结构的任意树。所以预处理会考虑时间复杂度。不过谢谢! 如果你想对一棵树进行一次查询,那么最坏情况的时间复杂度是 O(n),因为你可能必须查看每个节点。最坏情况下的空间复杂度为 O(n),因为在退化树中,您可能必须维护包含树中每个节点的路径。鉴于您概述的限制,我认为您无法提高复杂性。 【参考方案1】:

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

思路如下: 欧拉路径中出现的两个节点越多,它们的 LCA 就越高。 IE。 index(a) < index(b) < index(c) => dist_to_root(LCA(a, b)) >= dist_to_root(LCA(a, c))

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

其中一个会给出问题的最佳解决方案。

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

内存复杂度为 O(n)

【讨论】:

但是创建索引列表不需要 O(n) 时间吗? @JimMischel 是的,但您只需要在预处理期间执行一次。 请注意,LCA = "最低共同祖先:和"欧拉路径" = "树的欧拉图表示" (en.wikipedia.org/wiki/Euler_tour_technique),这也可以将 LCA 问题转换为“范围最小查询”,您也可以在 O(log N) 中执行此操作。请参阅 geeksforgeeks.org/find-lca-in-binary-tree-using-rmq 和 en.wikipedia.org/wiki/Range_minimum_query @MattTimmermans 是的,我知道。它甚至可以在 O(1) 中完成。 OP已经写过他知道如何完成这项任务,所以我没有在回答中解释。 @user38034 谢谢!我会试一试。是的,通过在预处理中计算欧拉路径和 BST,查询可以在 O(log n) 时间复杂度内完成。考虑到您的回复,这可能会被推到 O(log log n) 使用y-fast-tries。【参考方案2】:

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

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

要找到正确的父级,您可以进行二分搜索。例如。类似于二元提升的东西。这将增加 log(n) 的另一个因素。

【讨论】:

谢谢!有没有办法把这个方法塞进线性空间复杂度? @DannyDannyDanny 不,我不这么认为。

以上是关于如何找到具有某个标签的后代叶节点的最低祖先?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery---[jQuery筛选之::祖先,后代,同胞,过滤,判断]

如何在任何二叉树中找到两个节点的最低共同祖先?

如何在任何二叉树中找到两个节点的最低共同祖先?

找到两个Tree节点的最低共同祖先,而不参考root?

LeetCode算法题-Lowest Common Ancestor of a Binary Search Tree

在有向无环图中找到最低共同祖先的算法?