Lowest Common Ancestor of a Binary Tree — LC Medium

Companies: Facebook, Amazon, Microsoft

236. Lowest Common Ancestor of a Binary Tree

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).”

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Example 3:

Input: root = [1,2], p = 1, q = 2
Output: 1

Constraints:

  • The number of nodes in the tree is in the range [2, 105].
  • -109 <= Node.val <= 109
  • All Node.val are unique.
  • p != q
  • p and q will exist in the tree.

My first approach: DFS traversal, with some stopping conditions

as you traverse through the DFS method, when the node is either equal to p or q, stop searching and jump to searching the right section. if you find another p or q, then return the original node. if you don’t find anything, then return either left or right (first node that you found first) since failure to find another node in other branch means the node is inside of the subtree that we stopped finding.

An illustration is as follows:

that is the base case example, but it is possible that the node itself becomes lowest common ancestor of the other node. illustration for that case is as follows:

code is as follows:

# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# Implementation of DFS

# covering base case
if not root:
return None

return self.helperDFS(root, p, q)

def helperDFS(self, node, p, q):
if not node:
return False

if node == p or node == q:
return node

left = self.helperDFS(node.left, p, q)
right = self.helperDFS(node.right, p, q)

if left and right:
return node

return left or right

Time complexity: O(N) as the worst case

Space complexity: O(1)

Lets compile our recursive solution that we just built

# input goes into Solution.lowestCommonAncestor(root, p, q)

# check if the root is None. it is Not. so pass first if loop

# returns the output of the recursive function that we wrote (helperDFS)

# helperDFS initiates with input root, p, q

# checks if the current input node is None. no. currently it is node 3

# checks if 3 is equal to 5 or 1, no.

# recursive call to check on the left subtree of 3

## one level down, 5 is equal to p, so return 5

# recursive call to check on the right subtree of 3

## one level down, 1 is equal to q, so return 1

# left and right values are both not None, so return the original node 3

# function ends with return output of 3

--

--

Data Scientist, SWE + MLE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store