Explain
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).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
Example
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.
Solve
attempt 1
# 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':
return common(root, p, q)
def common(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if (not root):
return None
if (root == p or root == q):
return root
if (cover(root.left, p) and cover(root.left, q)):
return common(root.left, p, q)
if (cover(root.right, p) and cover(root.right, q)):
return common(root.right, p, q)
return root
def cover(root: TreeNode, p: TreeNode) -> bool:
if (not root):
return False
if (root == p):
return True
return cover(root.left, p) or cover(root.right, p)
performance 1
Time Limit Exceeded
attempt 2
# 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, p, q):
if (root in (None, p, q)):
return root
left, right = (self.lowestCommonAncestor(kid, p, q)
for kid in (root.left, root.right))
return root if left and right else left or right
performance 2
Runtime: 120 ms, faster than 8.98% of Python3 online submissions for Lowest Common Ancestor of a Binary Tree.
Memory Usage: 42.1 MB, less than 5.55% of Python3 online submissions for Lowest Common Ancestor of a Binary Tree.
attempt 3
# 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':
level = [root] # 遍历整棵树
dic = {root: None} # 构建了一个每个节点的父节点的 map,空间换时间
while p not in dic or q not in dic:
node = level.pop()
if node.left:
level.append(node.left)
dic[node.left] = node
if node.right:
level.append(node.right)
dic[node.right] = node
ans = set() # 将p的所有父节点都放到 ans
while p:
ans.add(p)
p = dic[p]
while q not in ans: # 从q开始,找到的第一个跟p相同的父节点就是LCA
q = dic[q]
return q
performance 3
Runtime: 84 ms, faster than 75.25% of Python3 online submissions for Lowest Common Ancestor of a Binary Tree.
Memory Usage: 17.8 MB, less than 91.67% of Python3 online submissions for Lowest Common Ancestor of a Binary Tree.