查找树搜索失败的最低命令祖先(不是算法问题,而是Java问题)

查找树搜索失败的最低命令祖先(不是算法问题,而是Java问题),java,tree,binary-tree,binary-search-tree,divide-and-conquer,Java,Tree,Binary Tree,Binary Search Tree,Divide And Conquer,非常简单的树问题,不知何故结果为空(应该是1,因为1是2&3的父节点),无法找到原因。该方法本身已经通过Leetcode在线评审 以下是问题的链接: 给定一棵二叉树,找到树中两个给定节点的最低共同祖先(LCA) 根据维基百科上LCA的定义:“两个节点v和w之间的最低共同祖先被定义为T中的最低节点,该节点的v和w都是其后代(我们允许一个节点是其自身的后代)。” TreeNode的定义如下: public class TreeNode { public int val; pub

非常简单的树问题,不知何故结果为空(应该是1,因为1是2&3的父节点),无法找到原因。该方法本身已经通过Leetcode在线评审

以下是问题的链接:

给定一棵二叉树,找到树中两个给定节点的最低共同祖先(LCA)

根据维基百科上LCA的定义:“两个节点v和w之间的最低共同祖先被定义为T中的最低节点,该节点的v和w都是其后代(我们允许一个节点是其自身的后代)。”

TreeNode的定义如下:

public class TreeNode {
     public int val;
     public TreeNode left, right;
     public TreeNode(int val) {
         this.val = val;
         this.left = this.right = null;
     }
}

由于这一行代码,正在发生错误

if (root == null || root == t1 || root == t2) 
在执行此方法时,请仔细考虑要比较的内容

TreeNode result = test.lowestCommonAncestor(root, target1, target2);
调用LCA方法时,第一条if语句中的任何条件都不会计算为true,因为没有一条语句为true,这是正确的。但是,现在让我们来看第一个递归调用

TreeNode left = lowestCommonAncestor(root.left, t1, t2);
TreeNode right = lowestCommonAncestor(root.right, t1, t2);
对于
最低的公共祖先(root.left,t1,t2)
,请仔细考虑第一条if语句<在这种情况下,code>root现在是
node2
,而t1和t2仍然是main中定义的节点
target1
target2
。但是等等,这就是问题发生的原因。您可能希望语句
root==t1
的计算结果为true,但它的计算结果不是true,原因如下
node2
target1
是两个不同的对象,Java的
==
操作符并没有做您认为它在这里做的事情。使用
=
运算符比较对象时,将比较对象的地址,而不是对象的实际内容。因此,由于
node2
target1
在程序中占用不同的数据空间,因此它们的地址不同。您将看到
=
运算符更常用于比较Java中的基本类型,如int和char,因为它与比较对象不同。这就是为什么您会看到Java中用于比较字符串的
.equals
方法,因为字符串是对象

那么解决方案是什么?

在TreeNode类中创建一个
equals
方法,该方法返回一个布尔值并将另一个TreeNode对象作为参数。另外,请确保此方法是实例方法而不是静态方法,以便此方法在代码中的执行如下所示:

public boolean equals(TreeNode node){ //method address
    //rest of the method has to be implemented yourself
    //ask yourself, how are two treenodes considered equal in your situation?
}
最后,将
root==t1
替换为

root.equals(t1)
root.equals(t2)
root==t2
with

root.equals(t1)
root.equals(t2)
您可以尝试以下方法:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode t1, TreeNode t2) {
       if((search(root,t1)==null)||(search(root,t2)==null)
           return null;           
       if(search(root.left,t1)!=null)
       {          
           if(search(root.left,t2)!=null)
              return lowestCommonAncestor(root.left,t1,t2);
       }
       else if(search(root.right,t2)!=null)            
           return lowestCommonAncestor(root.right,t1,t2);
       return root;                                   
}
search
method搜索树中的树节点,我把它留给您;)

解释 首先,我们检查
root
树是否包含节点
t1
t2
,如果
root
不包含其中一个,我们将返回null,因为没有祖先

之后,我们在
root.left
中搜索
t1
,如果我们在
root.left
中搜索
t2
,如果我们找到它,那么最不常见的祖先必须在
root.left
中,但我们还不能确定它,所以我们递归地调用
最低共同祖先(root.left,t1,t2)
的方法

现在,如果我们在右边找到
t2
,在右边找到
t1
,那么最不常见的祖先在
右边,我们递归调用

在所有其他情况下,我们返回root,因为
t1
位于左侧,
t2
位于右侧,反之亦然。在这两种情况下,root是一个共同祖先(因为我们的检查),所以它是最不共同的祖先


如果允许我们在每个
TreeNode
中都有一个
parent
指针,那么更好的算法是从
t1.parent
向树上走,并且只在
p=t1时停止。parent
(或者
t1.parent.parent
,你知道了)是
t2
的祖先

树节点不需要指向父节点的指针吗?这是Leetcode提供的树节点,所以我不认为指针是一个选项。你是对的,我忽略了我试图比较两个对象。因此,我认为最简单的方法是将if(root==null | | root==t1 | | root==t2)更改为if(root==null | | root.val==t1.val | root.val==t2.val)