Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
修改二叉树的LCA代码以检查Java中是否存在节点_Java_Algorithm_Binary Tree_Least Common Ancestor - Fatal编程技术网

修改二叉树的LCA代码以检查Java中是否存在节点

修改二叉树的LCA代码以检查Java中是否存在节点,java,algorithm,binary-tree,least-common-ancestor,Java,Algorithm,Binary Tree,Least Common Ancestor,我有一个代码,它计算二叉树中给定两个节点的最小公共祖先。 目前,它假定两个节点都存在。我可以编写一个helper方法来检查节点是否存在,然后调用LCABT方法。这需要遍历树两次。我想知道是否有一种方法来检查和处理当节点不存在我的当前代码时的情况 //LCA of Binary tree public static Node LCABT(Node root, int v1, int v2){ if (root==null)

我有一个代码,它计算
二叉树中给定两个
节点的
最小公共祖先。
目前,它假定两个节点都存在。我可以编写一个helper方法来检查节点是否存在,然后调用
LCABT
方法。这需要遍历树两次。我想知道是否有一种方法来检查和处理当节点不存在我的当前代码时的情况

//LCA of Binary tree
            public static Node LCABT(Node root, int v1, int v2){
                if (root==null)
                    return null;
                if (root.data==v1 || root.data==v2){
                    return root;
                }
                Node left = LCABT(root.left,v1,v2);
                Node right = LCABT(root.right,v1,v2);

                if(left!=null && right!=null)
                    return root;
                else if (left!=null)
                     return left;
                else  if (right!=null)
                       return right;
                return null;
            }

使函数返回一对
(状态,lca)
<代码>状态
必须是以下之一:

0: Neither v1 nor v2 appear at or under root; lca is meaningless.
1: Only v1 appears at or under root; lca is meaningless.
2: Only v2 appears at or under root; lca is meaningless.
3: Both v1 and v2 appear at or under root, and have LCA equal to lca.
该功能应首先检查基本情况:

LCABT(Node root, int v1, int v2) {
    if (root == null) then return (0, null);
否则,在其左侧和右侧子对象上递归,以查看其中一个是否自行解决问题:

    (s1, lca1) = LCABT(root.left, v1, v2);
    (s2, lca2) = LCABT(root.right, v1, v2);
如果
s1
s2
为3,则已找到LCA(分别为
lca1
lca2
),并可立即返回。(事实上,在第二次调用
LCABT()
之前,您甚至可以通过检查
s1==3
来获得加速:如果是,那么我们已经有了LCA,不需要第二次调用。)

否则,设置
s=s1 | s2
(即按位或)。如果
s==3
,那么我们知道
root
是LCA,但我们还没有考虑它可以成为LCA的所有方式:当
v1
v2
中只有一个位于其子级或其下时,它仍然可以成为LCA,前提是另一个值位于
root
本身:

    s = s1 | s2;
    if (root.data == v1) then s = s | 1;
    if (root.data == v2) then s = s | 2;
现在所有
root
是LCA的情况都意味着
s==3
,因此如果
s==3
,我们可以立即返回
(3,root)

    if (s == 3) then return (3, root);
否则,
v1
v2
中最多有一个在
根目录下,因此我们应该返回一个值,指示它是哪一个:

    return (s, null);
}
最后,对
LCABT()
的原始顶级调用显然应该只在函数返回值为3的
状态时才认为函数成功


与您的算法相比,此算法的另一个优点是它不会被树中的
v1
v2
的重复副本所愚弄。

@NiklasB。“而不是O(logn),这是可能实现的”-这只是在一个平衡的二元搜索树中,或者如果你知道节点的位置。@Dukeling:是的,我现在看到了。我假设是一个搜索树,但可能不是。尽管如此,该算法仍不应该以这里给出的形式工作。@NiklasB:我不明白你的意思。但是代码现在可以工作了。如果两者都不存在,则返回null。但是,如果其中一个存在,而另一个不存在,我将返回作为节点存在的一个,这不会纠正我的愚蠢。我看不懂代码。至于你的问题,如果
v1!=
在某个时刻,如果(left!=null&&right!=null)
都存在,则会出现这种情况。您只需记住是否发生了这种情况,或者在递归期间将其传递到调用堆栈。如果不存在,则树中最多存在一个节点(假设树中没有重复节点)。问题是一个节点存在,另一个节点不存在。例如,我有root.data=5、v1=5和v2=10,假设v2不存在。我当前的代码,只返回root,因为root.data=v1,但它没有检查v2是否存在..希望有意义..当按位OR操作开始时,我迷路了。在那之后,我很难理解。为什么设置s=s1 | s2。我猜运行时间仍然是O(n),因为s将等于3,当且仅当s1和s2中的一个为1,另一个为2;b=最大值(s1,s2);如果(a==1&&b==2),则s=3,否则s=b。更冗长的方法是写出一整套
if
语句,但我不会这么做——如果真值表仍然没有点击,就写出它。是的,运行时是O(n)。还有一件事可能会有所帮助:我们将所有
状态
值,包括
s
,视为2位“位集”。位0(LSB)=1 iff v1出现在根目录或根目录下,位1=1 iff v2出现在根目录或根目录下。按位OR对应于取2个位集的并集;如果(root.data==v2),则s=s | 2应该在
(s1,lca1)=LCABT(root.left,v1,v2)之前;(s2,lca2)=LCABT(root.right,v1,v2)
    return (s, null);
}