如何使用Java实现二叉树的最低公共祖先?

如何使用Java实现二叉树的最低公共祖先?,java,algorithm,binary-tree,lowest-common-ancestor,Java,Algorithm,Binary Tree,Lowest Common Ancestor,我遇到了下面的实现,花了一些时间,但仍然不能理解这个想法。有人能逐行解释一下它在做什么吗?我只是不明白在什么时候它可以决定一个节点是一个祖先 多谢各位 public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null || root == p || root == q) return root;

我遇到了下面的实现,花了一些时间,但仍然不能理解这个想法。有人能逐行解释一下它在做什么吗?我只是不明白在什么时候它可以决定一个节点是一个祖先

多谢各位

public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q)  return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left != null && right != null)   return root;
        return left != null ? left : right;
    }
}
如果当前
根节点
null,则在当前子树上不存在pq
共同祖先
,因此返回
null root==null

如果pq等于
root
。我假设p=root,这里对于q,它要么是p
子代
,要么是p
非子代
但是在这种情况下,不需要遍历p的子树,因为如果前一种情况pq的祖先,那么只需返回p==root,否则直接返回p,它不会产生错误,尽管在这种情况下p对于语句
if(left!=null&&right!=null)返回root
我稍后会解释

    TreeNode left = lowestCommonAncestor(root.left, p, q);
    TreeNode right = lowestCommonAncestor(root.right, p, q);
现在存在几种可能的情况:
1.p和q都是根的后代。左
2.p和q都是根的后代。对
3.这两个节点一个是根的
后代。左侧是根的
后代。右侧


这两个
递归语句
用于查找p和q的
共同祖先(表示1,2用于查找p和q的else用于3


此语句用于处理3的
对应结果
,p和q存在根的
左子树和右子树
,因此
祖先


此语句用于处理1,2的
相应结果
pq存在相同的左或右子树。

TreeNode*LowersCommon祖先(TreeNode*root,TreeNode*p,TreeNode*q){
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (root == NULL || root->val == p->val || root->val == q->val ||
        (p->val < root->val && root->val < q->val) ||
        (q->val < root->val && root->val < p->val)) {
        return root;
        }
    else if (root->val < p->val) return lowestCommonAncestor(root-> right, p, q);
    else return lowestCommonAncestor(root->left, p, q);
如果(root==NULL | | root->val==p->val | | root->val==q->val|| (p->valval&&root->valval)|| (q->valval&&root->valval)){ 返回根; } 否则如果(root->valval)返回最低的公共祖先(root->right,p,q); 否则返回最低的公共祖先(根->左,p,q);

这是C++中的答案,但是只要你把'->'转换成'.'语法,它应该非常相似。它是递归函数,它检查当前叶子的左、右子,一旦第一个if语句条件是真的,它就意味着它识别了最低的共同祖先,因为如果它的一个孩子都更大,它就是MEA。ns表示它是最小的值

例如:给定2作为其根,1和4作为其子项(分别为左和右),1低于根,但4不是,因此2是最小的公分母。它将在第一次运行时停止


如果你自己画一棵二叉树并测试每一步,它会更有意义。

标记树分支中是否存在一个数字的基本思想是使用非空指针表示找到的数字,使用指针表示未找到的数字

一旦找到一个号码(
p
q
),或者当
null
时,调用堆栈就会回退。之后,调用堆栈会给出一个明确的指示,表明没有搜索到的号码

有四种可能的情况:

1.)双亲都是单亲

                      root
                      /  \ 
            Leftsubtree  Rightsubtree
                p/q        q/p
在这种情况下,在下面的代码中,如果(left!=null&&right!=null)返回root;

2)另一方的父母之一

      q/p                     p/q
      /            OR          \ 
Leftsubtree                 Rightsubtree
  p/q                           q/p
在这种情况下,如果(root==null | | root==p | | root==q)返回root;

3.)它们中的任何一个都不在树上。 这种情况将未被检测到。如案例2所示,函数立即返回,无需进一步遍历并在其下方的树中查找对应项

4.)树上没有一个

第一行
if(root==null…return;
将对每个不存在的子级执行。最终结果将是
null
return,因为找不到任何数字


逐行代码解释

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if(root == null || root == p || root == q)  return root;

    /* (root == null)  This proves that root is not in the branch of tree of our interest. Returning null would means NOTFOUND.*/
    /* (root == p || root == q) either p or q or both are found. Returning non-null root would means FOUND. */

    /*Check for presence in leftsubtree */
    TreeNode left = lowestCommonAncestor(root.left, p, q);

    /*Check for presence in rightsubtree */
    TreeNode right = lowestCommonAncestor(root.right, p, q);

    /*            root
                  /  \ 
        leftsubtree  Rightsubtree
            p/q        q/p

    */
    if(left != null && right != null)   return root; //both the numbers are found inside tree under root 

    // left or right subtree OR both don't have p or q. Return the overall find result under root.
    return left != null ? left : right;
}

这是第一个直接回答
请逐行解释[此LCA实施]正在做什么?
。它可以明确指出,对于“外部”使用,它假定p和_q_都在根目录树中,而在“内部”过程中/递归使用,它依赖于这一点,但并不总是如此,在
LowestCommonSenator()
中有相同之处。让我指出“解决方案”问题中提供的缺少文档注释和行内注释。递归函数可能很难理解。将它们绘制在纸上会有帮助。这里的代码是这个答案中的代码的一个稍微紧凑的版本:@Hulk无意冒犯,这个差异完全不相关,即使对于编译器来说也是如此。@SauravSahu是的,我同意t它是等价的。区别纯粹是风格和评论。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (root == NULL || root->val == p->val || root->val == q->val ||
        (p->val < root->val && root->val < q->val) ||
        (q->val < root->val && root->val < p->val)) {
        return root;
        }
    else if (root->val < p->val) return lowestCommonAncestor(root-> right, p, q);
    else return lowestCommonAncestor(root->left, p, q);
                      root
                      /  \ 
            Leftsubtree  Rightsubtree
                p/q        q/p
      q/p                     p/q
      /            OR          \ 
Leftsubtree                 Rightsubtree
  p/q                           q/p
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if(root == null || root == p || root == q)  return root;

    /* (root == null)  This proves that root is not in the branch of tree of our interest. Returning null would means NOTFOUND.*/
    /* (root == p || root == q) either p or q or both are found. Returning non-null root would means FOUND. */

    /*Check for presence in leftsubtree */
    TreeNode left = lowestCommonAncestor(root.left, p, q);

    /*Check for presence in rightsubtree */
    TreeNode right = lowestCommonAncestor(root.right, p, q);

    /*            root
                  /  \ 
        leftsubtree  Rightsubtree
            p/q        q/p

    */
    if(left != null && right != null)   return root; //both the numbers are found inside tree under root 

    // left or right subtree OR both don't have p or q. Return the overall find result under root.
    return left != null ? left : right;
}