📌  相关文章
📜  检查两个节点是否在树中的同一路径上 | 2套(1)

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

检查两个节点是否在树中的同一路径上

在树结构中,有时需要判断两个节点是否在同一路径上。本文将介绍两种方法。

方法一:DFS

通过深度优先搜索(DFS),可以遍历整棵树,逐个节点检查是否在同一路径上。

def is_same_path_dfs(root, node1, node2):
    def dfs(node, path):
        if not node:
            return False
        path.append(node)
        if node == node1 or node == node2:
            return path
        left_path = dfs(node.left, path)
        right_path = dfs(node.right, path)
        if left_path:
            return left_path
        if right_path:
            return right_path
        path.pop() # 回溯

    path1 = dfs(root, [])
    path2 = dfs(root, [])
    if node1 not in path1 or node2 not in path2:
        return False
    for i, node in enumerate(path1):
        if node == node1:
            break
    for j, node in enumerate(path2):
        if node == node2:
            break
    return i == j

上述代码中,首先定义了一个内嵌函数 dfs(),用于遍历整棵树。该函数的参数 node 表示当前处理的节点,path 存储从根节点到当前节点的路径。当遇到 node1node2 节点时,函数返回当前路径。如果遍历完整棵树后没有找到 node1node2 节点,则返回 False。在遍历完一个节点后,需要对路径进行回溯,即将当前节点从路径 path 中弹出。最后,分别遍历两次树,并分别获得从根节点到 node1node2 的路径,判断这两条路径最后一个相同节点的位置是否相同,如果相同则说明这两个节点在同一路径上,返回 True,否则返回 False。

该方法的时间复杂度为 $O(n)$,空间复杂度为 $O(h)$,其中 $n$ 是树的节点数,$h$ 是树的高度。

方法二:LCA

通过求解两个节点的最近公共祖先(LCA),可以判断这两个节点是否在同一路径上。

def is_same_path_lca(root, node1, node2):
    def find_lca(node, a, b):
        if not node or node == a or node == b:
            return node
        left = find_lca(node.left, a, b)
        right = find_lca(node.right, a, b)
        if left and right:
            return node
        return left or right

    lca = find_lca(root, node1, node2)
    if not lca:
        return False
    queue = [(lca, 1)]
    while queue:
        node, height = queue.pop()
        if node == node1:
            i = height
        if node == node2:
            j = height
        if hasattr(node, 'left'):
            queue.append((node.left, height + 1))
            queue.append((node.right, height + 1))
    return i == j

上述代码中,首先定义了一个内嵌函数 find_lca(),用于查找节点 node1node2 的最近公共祖先(LCA)。该函数的参数 node 表示当前处理的节点,ab 分别表示两个节点。当遍历到节点 a 或节点 b 时,函数返回该节点。当左子树和右子树中同时包含节点 a 和节点 b 时,该节点为 LCA。在遍历完一棵子树后,如果没有找到节点 a 和节点 b 的 LCA,则返回更深一层的子树。之后,先找到 node1node2 的 LCA,然后遍历整棵树,计算出 node1node2 到 LCA 的距离 $i$ 和 $j$,最后比较两个距离是否相等即可。

该方法的时间复杂度为 $O(n)$,空间复杂度为 $O(h)$,其中 $n$ 是树的节点数,$h$ 是树的高度。

总结

本文介绍了两种方法检查两个节点是否在树中的同一路径上,分别是 DFS 和 LCA。DFS 遍历整棵树,逐个节点检查是否在同一路径上;LCA 求解两个节点的最近公共祖先,然后算出两个节点到 LCA 的距离。两种方法的时间复杂度和空间复杂度均为 $O(n)$ 和 $O(h)$,其中 $n$ 是树的节点数,$h$ 是树的高度。