返回

手撸二叉树之二叉树的最近公共祖先

前端

大家好,今天我将带大家一起探索二叉树中两个节点的最近公共祖先。什么是最近公共祖先呢?我们先来看一个例子。

给定二叉树:[3,5,1,6,2,0,8,null,null,7,4],其中 5 和 1 是两个节点。它们的最近公共祖先是 3。

再举一个例子,给定二叉树:[3,5,1,6,2,0,8,null,null,7,4],其中 5 和 4 是两个节点。它们的最近公共祖先是 5。

现在我们已经了解了什么是最近公共祖先,接下来我们就来看一下如何求解。我们首先来看一种简单的递归算法:

  1. 如果根节点为空,则返回空。
  2. 如果根节点是其中一个节点,则返回根节点。
  3. 如果根节点不是其中一个节点,则分别递归地查找左子树和右子树。
  4. 如果在左子树和右子树中都找到了节点,则返回根节点。
  5. 如果只在左子树或右子树中找到了一个节点,则返回找到的节点。

代码如下:

def lowest_common_ancestor(root, p, q):
    if not root:
        return None
    if root == p or root == q:
        return root
    left = lowest_common_ancestor(root.left, p, q)
    right = lowest_common_ancestor(root.right, p, q)
    if left and right:
        return root
    return left or right

这种算法的时间复杂度是 O(n),空间复杂度是 O(h),其中 n 是二叉树的节点数,h 是二叉树的高度。

现在我们再来介绍一种更优的算法:

  1. 我们先将二叉树转换成一个哈希表,其中键是节点的值,值是节点的父节点。
  2. 然后,我们可以通过查找两个节点的父节点来找到它们的最近公共祖先。

代码如下:

def lowest_common_ancestor(root, p, q):
    parent = {}
    def dfs(node):
        if not node:
            return
        parent[node.val] = node.parent
        dfs(node.left)
        dfs(node.right)
    dfs(root)
    ancestors = set()
    while p:
        ancestors.add(p)
        p = parent[p]
    while q:
        if q in ancestors:
            return q
        q = parent[q]
    return None

这种算法的时间复杂度是 O(n),空间复杂度也是 O(n)。

希望通过本文,大家能够对二叉树的最近公共祖先有更深入的了解。