Tree 查找两个树节点的最低公共祖先,而不引用根?

Tree 查找两个树节点的最低公共祖先,而不引用根?,tree,binary-tree,lowest-common-ancestor,tree-search,Tree,Binary Tree,Lowest Common Ancestor,Tree Search,您被赋予两个节点p,和q,如何找到最低的共同祖先?(假设它们都属于一棵很大的树) 您没有对树的根的引用 最有效的方法是什么? 到目前为止,我唯一的想法就是 (1) 选择一个节点p(与哪个节点无关) (2) 搜索p的左子树,如果看到q,则返回p (3) 否则搜索p的右子树,如果看到q,则返回p (4) 否则,转到父级并搜索不存在的子树 包含p,如果找到q,则返回父级 (5) 否则,再上一级,重复(4)(搜索 不包含此父级) 这似乎效率极低。有更好的算法吗?您对允许使用的RAM数量有严格限制吗?如果

您被赋予两个节点
p
,和
q
,如何找到最低的共同祖先?(假设它们都属于一棵很大的树)

您没有对树的根的引用

最有效的方法是什么? 到目前为止,我唯一的想法就是

(1) 选择一个节点p(与哪个节点无关)

(2) 搜索p的左子树,如果看到q,则返回p

(3) 否则搜索p的右子树,如果看到q,则返回p

(4) 否则,转到父级并搜索不存在的子树 包含p,如果找到q,则返回父级

(5) 否则,再上一级,重复(4)(搜索 不包含此父级)


这似乎效率极低。有更好的算法吗?

您对允许使用的RAM数量有严格限制吗?如果不是,我会提出如下建议:

class TreeNode {
    TreeNode parent;
    TreeNode left;
    TreeNode right;

    // other data fields omitted - not relevant
}
直觉的想法如下。我们同时从两个节点开始。在循环的每次迭代中,我们从两个节点向上走一步。每当我们看到一个节点,我们就把它放在我们的映射中(应该有O(1)个插入和检索/检查它是否已经在那里)。当我们遇到一个已经放在地图上的节点时,这一定是我们的解决方案


此代码的运行时间不得超过
max(d_p,d_q)
迭代次数,其中
d_p
d_q
分别表示树中
p
q
所处的深度级别。如果两个节点恰好都非常靠近根,这将是一个很大的优势。这还意味着代码甚至可以用于无限树(而您的解决方案将陷入无限循环)。

p
一次遍历一个步骤(并且只有一个父级)。在每个步骤中,完全向左和向右递归,查找
q
节点。如果找到,则返回true,否则返回false。一路上,当您触摸每个节点时,将其标记为dirty,这样您就不必在更高级别重复递归。
visited_nodes = {}    // something like a HashMap, with O(1) insert and retrieval
node1 = p
node2 = q

while True:
    if node1 == null and node2 == null:    // the nodes don't seem to be in same tree
        return null    // or failure or anything like that

    if node1 is not null:
        if node1 in visited_nodes:    // node1 must be lowest common ancestor
            return node1
        else:
            visited_nodes.insert(node1)    // remember that we've seen this node
            node1 = node1.getParent()

    if node2 is not null:
        if node2 in visited_nodes:    // node2 must be lowest common ancestor
            return node2
        else:
            visited_nodes.insert(node2)    // remember that we've seen this node
            node2 = node2.getParent()