📌  相关文章
📜  检查两个节点是否在根节点的同一子树中(1)

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

检查两个节点是否在根节点的同一子树中

在树结构中,我们可能需要检查两个节点是否在根节点的同一子树中,即它们是否具有共同的祖先节点。

方法一:从根节点开始遍历

我们可以从根节点开始遍历整棵树,寻找每个节点的祖先,然后比较两个节点的祖先是否相同。如果相同,则它们在同一子树中,否则不在。

# 定义二叉树节点类
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# 寻找一个节点的祖先列表
def find_ancestor(root, node, path):
    if not root:
        return False
    
    path.append(root)
    
    if root == node:
        return True
    
    if (root.left and find_ancestor(root.left, node, path)) or \
    (root.right and find_ancestor(root.right, node, path)):
        return True
    
    path.pop()
    return False

# 检查两个节点是否在同一子树中
def is_same_subtree(root, p, q):
    path_p = []
    path_q = []
    
    find_ancestor(root, p, path_p)
    find_ancestor(root, q, path_q)
    
    if len(path_p) <= 1 or len(path_q) <= 1 or path_p[0] != path_q[0]:
        return False
    
    i = 1
    while i < len(path_p) and i < len(path_q):
        if path_p[i] != path_q[i]:
            break
        i += 1
    
    return path_p[i-1]

时间复杂度为 O(n),其中 n 是树中节点的数量,空间复杂度为 O(n),因为我们需要存储每个节点的祖先。

方法二:分别查找两个节点的路径

我们可以分别查找两个节点到根节点的路径,然后比较它们的路径是否相同。如果相同,则它们在同一子树中,否则不在。

# 查找从根节点到目标节点的路径
def find_path(root, node, path):
    if not root:
        return False
    
    path.append(root)
    
    if root == node:
        return True
    
    if (root.left and find_path(root.left, node, path)) or \
    (root.right and find_path(root.right, node, path)):
        return True
    
    path.pop()
    return False

# 检查两个节点是否在同一子树中
def is_same_subtree(root, p, q):
    path_p = []
    path_q = []
    
    find_path(root, p, path_p)
    find_path(root, q, path_q)
    
    if not path_p or not path_q:
        return False
    
    i = 0
    while i < len(path_p) and i < len(path_q):
        if path_p[i] != path_q[i]:
            break
        i += 1
    
    return path_p[i-1]

时间复杂度为 O(n),空间复杂度为 O(n),因为我们需要存储每个节点到根节点的路径。