Common Facebook Interview Question: Lowest Common Ancestor
We’ll go through two ways to solve this common problem asked at Facebook.
Question
Here’s the question:
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”As an example, if we’re given this tree, and p=1 and q=5 , then our answer will be 3.

First solution: Parent Map
Intuition
We know that we’ll have to first find both of the nodes. What if we built a map of the *parents* of the nodes?
e.g., for node p, if we could traverse upwards from p to the root of the tree, then for each node along the way, we can just see if it’s in the set of ancestors of q.
So we can start with a typical tree traversal function, which takes as input a current node, but also a parent node. We call this on the root node to build our parent map.
After building the parent map, we can add all the ancestors of p into a set.
Then, we traverse upwards, starting from q. If the next ancestor is in the set of p’s ancestors, then we return that node! Because we’re traversing upwards, we know that the first node that is also in p’s ancestor list must be the lowest common ancestor.
Here’s the code:

Algorithmic Complexity
The runtime here is O(N) — we do three traversals though!
The space complexity is also O(N) to store the parent map.
Second solution: Recursion
Intuition
We’ll come up with some logic to use at *every node*, so that when we do find the lowest common ancestor, we’ll be propagate that value up.
Let’s think through the conditions:
1/ If our current node is p or q, then we return the current node.
2/ If our current node doesn’t exist, we return None.
Let’s call our function recursively on node.left (call this value “left”) and node.right (call this value “right”).
3/ If left and right both exist, then we know our current node must be the lowest common ancestor.
4/ If left exists, but not right, return left.
5/ If right exists, but not left, return right.
1/ and 2/ are straightforward.
3/ we know that if one node is on the left, and one node is on the right, we should return our current node.
4/ means we found the lowest common ancestor on the left, and the answer is what was returned from 1/ or 3/, or passed up from another case of 4/ or 5/.
5/ Same as 4/, but for the right node.
Here’s the code:

The runtime here is O(N). We do need to do one traversal!
The space complexity is O(N), for the recursive call stack.
For more articles like this, follow me on Medium. Not a member yet? Join the community. Want more software engineering interview guides and coding question tips? Check out all of my writing organized by topic in this article.
If you have any requests for what I should write, please let me know!




