流水沉微

236. Lowest Common Ancestor of a Binary Tree

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.