二叉树两个节点求最近的公共祖先节点java代码实现

求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor)。

求解LCA问题,应该首先考虑二叉树的特性和二叉树结点的结构,先看二叉树是否是搜索二叉树,若为普通二叉树则要考虑二叉树结点是否包含指向父结点的指针。

一、二叉搜索树

二叉搜索树是排序过的 ,位于左子树的结点都比父结点小,位于右子树的结点都比父结点大。

求解思路:

从树根开始,该节点的值为t,如果t大于t1和t2,说明t1和t2都位于t的左侧,所以它们的共同祖先必定在t的左子树中,从t.left开始搜索;
如果t小于t1和t2,说明t1和t2都位于t的右侧,那么从t.right开始搜索;
如果t1

public int query(Node t1, Node t2, Node t) {  
    int left = t1.value;  
    int right = t2.value;  
    Node parent = null;  

    if (left > right) {  
        int temp = left;  
        left = right;  
        right = temp;  
    }  

    while (true) {  
        if (t.value < left) {  
            parent = t;  
            t = t.right;  
        } else if (t.value > right) {  
            parent = t;  
            t = t.left;  
        } else if (t.value == left || t.value == right) {  
            return parent.value;  
        } else {  
            return t.value;  
        }  
    }  
}

其中,parent用于处理t1是t2的祖先(或t2是t1的祖先)的情况。

二、普通二叉树(包含指向父结点的指针)

结点包含指向父结点的指针,这个问题可以转换成求两个链表的第一个公共结点,假设树结点中指向父结点的指针是parent,树的每一个叶结点开始都由一个指针parent串起来的链表,每个链表的尾结点就是树的根结点。那么输入的这两个结点位于链表上,它们的最低公共祖先结点刚好是这两个链表的第一个公共结点。

public int GetHigh(TreeNode root,TreeNode node){
    int len=0;
    while(node!=null){
        len++;
        node=node.parent;
    }
    return len;
}
public TreeNode GetLastCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2)  
{  

    if (root == null || node1 == null || node2 == null)  
        return null;  

    int len1 = GetHigh(root, node1);//一个链表的高度  
    int len2 = GetHigh(root, node2);//另一个链表的高度  
    //寻找两个链表的第一个交点  
    if(len1 != len2)  
    {  
        if (len1 < len2) {
            for(int i=0;ielse {
            for(int i=0;iwhile (node1 && node2 && node1 != node2)  
    {  
        node1 = node1.parent;  
        node2 = node2.parent;  
    }  

    if (node1 == node2)  
        return node1;  
    else  
        return null;  
} 

三、普通二叉树(不包含指向父结点的指针)

求解思路:
在二叉树根结点的左子树和右子树中分别找输入的两个结点,如果两个结点都在左子树,遍历当前结点的左子树,如果两个结点都在右子树,遍历当前结点的右子树,直到一个在当前结点的左子树,一个在当前结点的右子树,返回当前结点就是最低的公共祖先结点。

public boolean IsNodeInTree(TreeNode pRoot, TreeNode pNode)  
{  
    if (pRoot == null || pNode == null)  
        return false;  
    if (pNode == pRoot)  
        return true;  
    if (IsNodeInTree(pRoot.left, pNode) || IsNodeInTree(pRoot.right, pNode))  
        return true;  
    return false;  
}  
public TreeNode GetCommonAncestor(TreeNode pRoot, TreeNode node1, TreeNode node2)  
{  
    if (pRoot == null)  
        return null;  
    if (node1 == pRoot && IsNodeInTree(pRoot, node2) || node2 == pRoot && IsNodeInTree(pRoot, node1))  
        return pRoot;  

    boolean node1left = IsNodeInTree(pRoot.left, node1);  
    boolean node1right = IsNodeInTree(pRoot.right, node1);  
    boolean node2left = IsNodeInTree(pRoot.left, node2);  
    boolean node2right = IsNodeInTree(pRoot.right, node2);  
    if (node1left && node2right || node1right && node2left)  
        return pRoot;  
    if (node1left && node2left)  
        return GetCommonAncestor(pRoot.left, node1, node2);  
    if (node1right && node2right)  
        return GetCommonAncestor(pRoot.right, node1, node2);  
    return null;  
} 

你可能感兴趣的:(剑指offer算法题,java实现)