Finding the common ancestor in a binary tree

后端 未结 10 1196
悲哀的现实
悲哀的现实 2021-02-09 02:50

This question was asked to me in an interview: I have a binary tree and I have to find the common ancestor (parent) given two random nodes of that tree. I am also given a point

10条回答
  •  萌比男神i
    2021-02-09 03:19

    Make a level order traversal, and for each node we encounter we check its children. If they are the provided random nodes, then the ancestor node is found.

    EDIT1:

    Here is an outline

    struct _node {
       my_type data;
       struct _node *left;
       struct _node *right;
    }
    
    q = queue_create ();
    queue_insert (q, head);
    temp = head;
    while (!empty (q))
    {
        temp = queue_remove (q);
     if (
          (temp->left == my_random_node_1) && (head->right == my_random_node_2) ||
          (temp->left == my_random_node_2) && (head->right == my_random_node_1)
        )
        {
           /* temp is the common parent of the two target notes */
           /* Do stuffs you need to do */
        }
    
        /* Enqueue the childs, so that in successive iterations we can
         * check them, by taking out from the queue
         */
        push (q, temp->left);
        push (q, temp->right);
    }
    

    UPDATE

    The previous algorithm will only find common parents (direct ancestor), therefore if two randomly selected nodes if are not a child of common parent no answer would be found.

    The below algorithm will find common ancestors and not only parents.

    I think the following algorithm will work:

    Make a postorder traversal of the binary tree, and find for the random node 1 r1, if we find it then mark it in a state variable to be in state one, and keep finding for the second node, if found then update the state variable to state two, and stop searching more and return. The state variable should be passed by every node to its parents (recursively). The first node which encounters the state variable in state two is the common ancestor.

    The implementation of the algorithm is as follows:

    int postorder (node *p, int r1, int r2)
    {
      int x = 0; /* The state variable */
      if (p->data == TERMINAL_VAL)
        return x;
    
      /* 0x01 | 0x02 = 0x03 threfore 
       * state one is when x = 0x01 or x = 0x02
       * state two is when x = 0x03
       */
      if (p->data == r1)
        x |= 0x01;
      else if (p->data == r2)
        x |= 0x02;
    
      /* if we have x in state two, no need to search more
       */
      if (x != 0x03)
        x |= postorder (p->left, r1, r2);
      if (x != 0x03)
        x |= postorder (p->right, r1, r2);
    
      /* In this node we are in state two, print node if this node
       * is not any of the two nodes r1 and r2. This makes sure that
       * is one random node is an ancestor of another random node
       * then it will not be printed instead its parent will be printed
       */
      if ((x == 0x03) && (p->data != r1) && (p->data != r2))
      {
       printf ("[%c] ", p->data);
       /* set state variable to 0 if we do not want to print 
        * the ancestors of the first ancestor 
        */
       x = 0;
      }
    
      /* return state variable to parent
       */    
      return x;
    }
    

    I think this will work correctly, though i am still to prove the algorithm's correctness. There is one drawback, which is, if one node is a child of another node, then it will print only the node which is the parent of the other one, instead of printing the parent of them. If one of the random node is an ancestor of another random node then instead of printing the ancestor random node, it will print the parent of it. In the case in which one of the random node is the root node, it will print nothing, as it is always the ancestor of the other random node, and therefore their common ancestor does not exist. In this special case the function will return 0x03 in main and it can be detected.

    As this algorithm does a postorder traversal therefore it requires O(n) execution time and thus O(n) memory. Also as the search stops as soon both the nodes are found, the shallower the nodes the quicker the search ends.

    UPDATE

    Here are some mode discussions: How to find the lowest common ancestor of two nodes in any binary tree?

提交回复
热议问题