如何找到一棵树的最低共同祖先?

时间:2012-04-04 13:13:52

标签: algorithm tree

有没有办法不使用额外的空间来找到nary树的LCA。 我使用字符串保存了两个节点的预订并找到了公共前缀

3 个答案:

答案 0 :(得分:4)

如果节点“知道”它们的深度 - 或者您愿意允许空间计算节点的深度,则可以从较低节点备份到较高节点的相同深度,然后上升一个节点直到他们见面为止。

取决于“额外空间”在这种情况下的含义。你可以用一个整数来做 - 两个节点的深度差异。这太宽了吗?

另一种可能性是你没有父指针,你可以使用指针反转 - 每次遍历指针时,记住你来自的位置,记住下一次遍历的指针,然后就在下一个指针遍历,用后指针替换该指针。当你上树恢复它时你必须扭转它。这将一个指针的空间作为临时空间。另一个整数来保持深度,因为你的工作向下和向上。对于您寻找的两个节点同步执行此操作,以便您可以从较低的节点返回,直到在两次遍历中处于相同的高度,然后从两者中重新开始工作,直到您处于公共节点。这需要三个额外的内存 - 一个用于每个当前深度,一个用于在指针反转期间使用的临时内存。非常节省空间。值得吗?

答案 1 :(得分:2)

返回并为二叉树执行此操作。如果您可以为二叉树执行此操作,则可以为n-ary树执行此操作。

这是a link to LCA in a binary tree

以下是将其转换为n-ary树LCA后的样子:

  public class LCA {

    public static <V> Node<V> 
                lowestCommonAncestor(Node<V> argRoot, Node<V> a, Node<V> b) {

      if (argRoot == null) {
        return null;
      }

      if (argRoot.equals(a) || argRoot.equals(b)) {
        // if at least one matched, no need to continue
        // this is the LCA for this root
        return argRoot;
      }

      Iterator<Node<V>> it = argRoot.childIterator();
      // nr of branches that a or b are on, 
      // could be max 2 (considering unique nodes)
      int i = 0; 
      Node<V> lastFoundLCA = null;
      while (it.hasNext()) {
        Node<V> node = lowestCommonAncestor(it.next(), a, b);
        if (node != null) {
          lastFoundLCA = node;
          i++ ;
        }
        if (i >= 2) {
          return argRoot;
        }
      }

      return lastFoundLCA;
    }

  }

答案 2 :(得分:0)

同步遍历两个节点。

  • 从LCA = root开始;
  • 循环:
  • 找到A的步骤和B
  • 的步骤
  • 如果这些是相等的{LCA =步骤;下降A;下降B;转到循环; }
  • 已完成:LCA现在包含A和B的lca

C中的伪代码:

struct node {
        struct node *offspring[1234];
        int payload;
        };

        /* compare function returning the slot in which this should be found/placed */
int find_index (struct node *par, struct node *this);

struct node *lca(struct node *root, struct node *one, struct node *two)
{
struct node *lca;
int idx1,idx2;

for (lca=root; lca; lca=lca->offspring[idx1] ) {
    idx1 = find_index(lca, one);
    idx2 = find_index(lca, two);
    if (idx1 != idx2 || idx1 < 0) break;
    if (lca->offspring[idx1] == NULL) break;
    }
return lca;
}