【问题标题】:Lowest Common Ancestor of Binary Tree(Not Binary Search Tree)二叉树的最低共同祖先(不是二叉搜索树)
【发布时间】:2010-08-22 07:49:38
【问题描述】:

我尝试使用 Tarjan 的算法和网站上的一种算法来解决问题:http://discuss.techinterview.org/default.asp?interview.11.532716.6,但没有一个是清楚的。也许我的递归概念没有正确建立。请给小示范解释以上两个例子。我对 Union Find 数据结构有一个想法。

这看起来很有趣的问题。所以无论如何都必须解码问题。准备面试。

如果还有其他逻辑/算法,请分享。

【问题讨论】:

    标签: c algorithm data-structures


    【解决方案1】:

    LCA 算法试图做一件简单的事情:找出从有问题的两个节点到根的路径。现在,这两条路径将有一个共同的后缀(假设路径以根结尾)。 LCA 是后缀开始的第一个节点。

    考虑以下树:

                  r * 
                   / \
                s *   *
                 / \
              u *   * t
               /   / \
              * v *   *
                 / \
                *   *
    

    为了找到 LCA(u, v),我们进行如下操作:

    • 从 u 到根的路径:Path(u, r) = usr
    • 从 v 到根的路径:Path(v, r) = vtsr

    现在,我们检查通用后缀:

    • 常用后缀:'sr'
    • 因此 LCA(u, v) = 后缀的第一个节点 = s

    注意实际算法不会一直到根。他们使用 Disjoint-Set 数据结构在到达 s 时停止。

    解释了一组出色的替代方法here

    【讨论】:

    • 只有一条评论:树木通常(大部分)是平衡的。在这些情况下,使用不相交集数据结构的开销可能比简单地从 u 向上标记到根,然后从 v 向上搜索第一个标记的节点到根。
    【解决方案2】:

    既然你提到了工作面试,我想到了这个问题的变体,你被限制在 O(1) 内存使用。

    在这种情况下,请考虑以下算法:

    1) 从节点 u 到根扫描树,找到路径长度 L(u)

    2) 从节点 v 向上扫描树,找到路径长度 L(v)

    3) 计算路径长度差D = |L(u)-L(v)|

    4) 从根开始跳过较长路径中的 D 个节点

    5) 从两个节点并行向上走,直到碰到同一个节点

    6) 将此节点作为 LCA 返回

    【讨论】:

      【解决方案3】:

      假设您只需要解决一次问题(每个数据集),那么一种简单的方法是从一个节点(连同自身)收集祖先集,然后从另一个节点遍历祖先列表,直到找到上述集合的成员,它必然是最低的共同祖先。给出了伪代码:

      Let A and B begin as the nodes in question.
      seen := set containing the root node
      while A is not root:
          add A to seen
          A := A's parent
      while B is not in seen:
          B := B's parent
      B is now the lowest common ancestor.
      

      另一种方法是计算每个节点到房间的整个路径,然后从右侧扫描以查找公共后缀。它的第一个元素是 LCA。其中哪一个更快取决于您的数据。

      如果您需要找到多对节点的 LCA,那么您可以进行各种空间/时间权衡:

      例如,您可以预先计算每个节点的深度,这样您就可以避免每次都重新创建集合(或路径),方法是先从较深的节点走到较浅的节点的深度,然后将两个节点以锁定的步骤向根部移动:当这些路径相遇时,您就有了 LCA。

      另一种方法是在 depth-mod-H 处用它们的下一个祖先来注释节点,这样你首先解决一个类似但 H 倍小的问题,然后是第一个问题的 H 大小的实例。这在非常深的树上很好,通常选择 H 作为树的平均深度的平方根。

      【讨论】:

      • 如果允许您对树进行预处理,您可以做得更好。
      猜你喜欢
      • 2011-07-28
      • 2012-11-08
      • 2017-02-21
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 2020-08-16
      相关资源
      最近更新 更多