简体   繁体   中英

how to find lowest common ancestor of a nary tree?

Is there a way without using extra space to find LCA of nary tree. I did it using a string saving the preorder of both the nodes and finding common prefix

If nodes "know" their depth - or you're willing to allow the space to compute the depth of your nodes, you can back up from the lower node to the same depth of the higher node, and then go up one level at a time until they meet.

Depends on what "extra space" means in this context. You can do it with one integer - the difference in depths of the two nodes. Is that too much space?

Another possibility is given you don't have a parent pointer, you can use pointer reversal - every time you traverse a pointer, remember the location from which you came, remember the pointer you will next traverse, and then just before the next pointer traversal, replace that pointer with the back pointer. You have to reverse this when going up the tree to restore it. This takes the space of one pointer as a temporary. And another integer to keep the depth as you work your way down and up. Do this synchronously for the two nodes you seek, so that you can work your way back up from the lower one until you're at the same height in both traversals, and then work back up from both until you're at the common node. This takes three extra pieces of memory - one for each of the current depths, one for the temporary used during a pointer reversal. Very space efficient. Is it worth it?

Go back and do it for a binary tree. If you can do it for a binary tree you can do it for an n-ary tree.

Here's a link to LCA in a binary tree :

And here's how it looks after converting it to a n-ary tree 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;
    }

  }

Do a synchronous walk to both the nodes.

  • Start with LCA=root;
  • loop:
  • find the step to take for A and the step for B
  • if these are equal { LCA= the step; decend A; descend B; goto loop; }
  • done: LCA now contains the lca for A and B

Pseudocode in 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM