This problem was asked by Twitter.

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. Assume that each node in the tree also has a pointer to its parent.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

My Solution(C++):


#include <iostream>
#include <vector>

using namespace std;

struct node{
  // Binary Tree data structure
  int data;
  node *left, *right;
};


node *createNode(int val){
  // Function to create a binary tree node
  node *temp = new node;
  temp->data = val;
  temp->left = temp->right = NULL;
  return temp;
}


bool findPath(node *root, node *node_to_find, vector<node> &path){
  // Builds a vector of nodes from root to node_to_find
  if (root==NULL)
    return false;
  path.push_back(*root);
  if (root==node_to_find)
    return true;
  if ((root->left!=NULL && findPath(root->left,  node_to_find, path)) || \
     (root->right!=NULL && findPath(root->right,  node_to_find, path)))
        return true;
  path.pop_back();
  return false;
}


int findLCA(node *root, node *v, node *w){
  // Returns LCA of nodes v and w in a b. tree rooted under root
  vector<node> path_v,  path_w;
  findPath(root, v, path_v);
  findPath(root, w, path_w);
  int i = 0;
  while (i<path_v.size()){
    if (path_v[i].data != path_w[i].data) break;
    i++;
  }
  return path_v[i-1].data;
}


void test(){
  // Create and run a test case
  node *root = createNode(1);
  node *l = root->left = createNode(2);
  node *r = root->right = createNode(3);
  node *ll = root->left->left = createNode(4);
  node *lr = root->left->right = createNode(5);
  node *rl = root->right->left = createNode(6);
  node *rr = root->right->right = createNode(7);
  // vector<node> path;
  // findPath(root, rl, path);
  // for (int i=0; i<path.size(); i++){
  //   cout << path[i].data << endl;
  // }

  int lca = findLCA(root, rl, rr);
  cout << "V = " << rl->data << " W = " << rr->data << " LCA = " << lca << endl;

}


int main(){
  // runs the test
  test();
}

My Solution(Python):


from tree import Node


class TreeNode(Node):
    """
    Binary Tree data structure with inheritance from a vis lib with custom
    methods
    """
    def __init__(self, data):
        super(TreeNode, self).__init__(data=data)


def findPath(root, node, path):
    """
    Modifies path argument to store path from root to node
    """
    if root is None:
        return False
    path.append(root)
    if root==node:
        return True
    if (root.left is not None and findPath(root.left, node, path)) or   (root.right is not None and findPath(root.right, node, path)):
        return True
    path.pop()
    return False


def findLCA(root: TreeNode, v: TreeNode, w: TreeNode) -> TreeNode:
    """
    Finds LCA of nodes v and w for a tree with root 'root'
    """
    path_v = []
    path_w = []
    findPath(root, v, path_v)
    findPath(root, w, path_w)
    i = 0
    while i<min(len(path_v), len(path_w)):
        if path_v[i] != path_w[i]:
            break
        i+=1
    return path_v[i-1]


def main():
    """
    Builds a test case and runs test for LCA
    """
    root = TreeNode(1)
    l = root.left = TreeNode(2)
    r = root.right = TreeNode(3)
    ll = root.left.left = TreeNode(4)
    lr = root.left.right = TreeNode(5)
    rl = root.right.left = TreeNode(6)
    rr = root.right.right = TreeNode(7)
    root.prettyPrint(); print('\n')
    for v, w in [(ll, lr), (ll, rl), (r, ll), (l, ll)]:
        lca = findLCA(root, v, w)
        print('v=%s, w=%s, lca=%s' %(v.data, w.data, lca.data))


if __name__=='__main__':
    main()