最近公共祖先(LCA)问题 笔记

最近公共祖先(转载)

1、暴力对待
    如果是二叉查找树:寻找节点u, v 的最近公共祖先  步骤

    1、如果当前结点t 大于结点u、v,说明u、v都在t 的左侧,所以它们的共同祖先必定在t 的左子树中,

         故从t 的左子树中继续查找;

    2、如果当前结点t 小于结点u、v,说明u、v都在t 的右侧,所以它们的共同祖先必定在t 的右子树中,

         故从t 的右子树中继续查找;

   3、如果当前结点t 满足 u

   4、而如果u是v的祖先,那么返回u的父结点,同理,如果v是u的祖先,那么返回v的父结点。


示例:

public int query(Node t, Node u, Node v) {    
    int left = u.value;    
    int right = v.value;    
  
    //二叉查找树内,如果左结点大于右结点,不对,交换  
    if (left > right) {    
        int temp = left;    
        left = right;    
        right = temp;    
    }    
  
    while (true) {    
        //如果t小于u、v,往t的右子树中查找  
        if (t.value < left) {    
            t = t.right;    
  
        //如果t大于u、v,往t的左子树中查找  
        } else if (t.value > right) {    
            t = t.left;    
        } else {    
            return t.value;    
        }    
    }    
} 

二、普通的二叉树

            如果每个结点都有一个指针指向它的父结点,于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点。如果给出根节点,LCA问题可以用递归很快解决。而关于树的问题一般都可以转换为递归(因为树本来就是递归描述),参考代码如下:

        node getLCA(node root , node  node1, node node2)
 {
if(root==null) return null;
        if(root==node1 || root==node2) return root;
node left=getLCA(root.left, node1,node2);
        node right=getLCA(root.right , node1,node2);
        if(left != null && right != null)     
  return root;  
else if (left != null)  
    return left;  
    else if (right != null)  
        return right;  
    else   
        return null;  
} 
不论是针对普通的二叉树,还是针对二叉查找树,上面的解法有一个很大的弊端就是:如需N 次查询,则总体复杂度会扩大N 倍,故这种暴力解法仅适合一次查询,不适合多次查询。


后面的链接有更多的内容!

转载自:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.03.md

你可能感兴趣的:(算法,学习)