📌  相关文章
📜  BST中两个节点之间的最短距离(1)

📅  最后修改于: 2023-12-03 15:13:43.486000             🧑  作者: Mango

BST中两个节点之间的最短距离

二叉搜索树(BST)是一种非常常见的数据结构,它具有以下特点:

  • 左子树上所有节点的值均小于根节点的值
  • 右子树上所有节点的值均大于根节点的值
  • 左右子树也分别为二叉搜索树

在一颗BST中,如果我们想要计算两个节点之间的最短距离,我们需要做些什么呢?

方法一:暴力枚举

首先一个朴素的想法可能是暴力枚举所有的节点对,计算它们之间的距离,然后找到最小值。

def min_distance(root, p, q):
    def distance(node, target):
        if node is None:
            return float('inf')
        if node == target:
            return 0
        if node.val > target.val:
            return distance(node.left, target) + 1
        if node.val < target.val:
            return distance(node.right, target) + 1

    min_dis = float('inf')
    for node in [p, q]:
        other = q if node == p else p
        dis = distance(root, node) + distance(root, other)
        min_dis = min(min_dis, dis)

    return min_dis 

这种方法的时间复杂度很高,为O(n^2),因为需要枚举所有节点对,计算距离。

方法二:递归寻找LCA

上面的方法效率太低,有没有更快的方法呢?

我们可以通过递归寻找BST中两个节点的最近公共祖先(LCA),然后计算两个节点到LCA的距离之和即可。对于递归寻找LCA,我们可以采用二叉树的递归查找算法。

def min_distance(root, p, q):
    def find_lca(node, p, q):
        if node is None:
            return None
        if node.val > p.val and node.val > q.val:
            return find_lca(node.left, p, q)
        elif node.val < p.val and node.val < q.val:
            return find_lca(node.right, p, q)
        else:
            return node

    def distance(node, target):
        if node is None:
            return float('inf')
        if node == target:
            return 0
        if node.val > target.val:
            return distance(node.left, target) + 1
        if node.val < target.val:
            return distance(node.right, target) + 1

    lca = find_lca(root, p, q)
    return distance(lca, p) + distance(lca, q)

时间复杂度为O(h),其中h为BST的高度,最坏情况下为O(n),因为BST可能退化成链表。

方法三:迭代寻找LCA

上述方法基于递归,有没有非递归的方法呢?

我们可以考虑利用BST的性质,通过迭代的方式寻找LCA。具体来说,我们从根节点开始,如果当前节点的值比p和q的值都大,说明p和q都在当前节点的左子树里,因此我们继续遍历当前节点的左子树;反之,如果当前节点的值比p和q的值都小,说明p和q都在当前节点的右子树里,因此我们继续遍历当前节点的右子树;否则说明当前节点就是p和q的LCA。

def min_distance(root, p, q):
    def distance(node, target):
        if node is None:
            return float('inf')
        if node == target:
            return 0
        if node.val > target.val:
            return distance(node.left, target) + 1
        if node.val < target.val:
            return distance(node.right, target) + 1

    lca = root
    while True:
        if lca.val > p.val and lca.val > q.val:
            lca = lca.left
        elif lca.val < p.val and lca.val < q.val:
            lca = lca.right
        else:
            break

    return distance(lca, p) + distance(lca, q)

时间复杂度同样为O(h)。

总结

以上三种方法都是比较常见的寻找BST中两个节点之间最短距离的方法。其中迭代寻找LCA的方法比较简洁高效,但需要注意终止循环的条件;而递归寻找LCA的方法比较容易理解,但需要调用函数进行递归,可能会占用较多栈空间。在实际应用中,需要根据具体情况选择合适的方法。