最近公共祖先


leetcode 美團筆試也考到了就是要找二叉樹兩個節點的第一個共同的祖先。對於樹,沒有規定,不一定是一顆二叉查找樹。

第一種情況:首先 如果這個樹是一個二叉樹的,並且是一顆二叉查找樹的話

由於二叉查找樹的左子樹節點比父節點小,右子樹節點比父節點大,則輸入兩個節點,只用從根節點開始比較,如果,如果當前節點比這兩個節點都大,則最低的公共父節點一定在左子樹中,那么遍歷左子樹節點。如果當前節點比兩個節點小,那么遍歷右子節點。這樣,找到的第一個值在二者之間的節點就是公共的最低的祖先。

代碼如下:(在leetcode的ac代碼)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) {
        if(node1.val>node2.val){
            TreeNode temp = node1;
            node1 = node2;
            node2 =temp;
        }
        if(root==null||root==node1||root==node2) return root;
        if(node1.val<root.val&&node2.val>root.val) return root;
        else if(node1.val<root.val&&node2.val<root.val) return lowestCommonAncestor(root.left,node1, node2);
        else  return lowestCommonAncestor(root.right,node1, node2);
        
        
    }
}

 

第二種情況:如果只是一般的二叉樹,不是搜索樹的話 可以用遞歸的方法:方法思路如下:收下看root是否為公共祖先,不是的話,則遞歸到左右節點(可能效率不怎么好)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
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;
    }
}

 

第三種 如果這個就是一個一般的樹  亦不一定是二叉樹。如何處理?思路就是找出這兩個節點的路徑,並存在鏈表中,則這兩個鏈表的交點就是最低公共祖先

實現如下:

    /*-------------------第二種情況--------------------------------------------*/
    //如果這個樹只是一個一般的樹 也不一定是是二叉樹。這里當做二叉樹來處理吧。不是二叉樹的情況也一樣的方法。
    
    public TreeNode fin_nearances3(TreeNode node1,TreeNode node2,TreeNode root){
        if(root==null||node1==root||node2==root) return root;
        List<TreeNode> path1 = new ArrayList<>();
        List<TreeNode> path2 = new ArrayList<>();
        
        
        findpath(root, node1, path1);
        findpath(root,node2,path2);
        return findlastcommonNode(path1, path2);
    }
    //找出節點P的路徑 存在path中,如果不存在的話就返回false
    public boolean findpath(TreeNode root,TreeNode p,List<TreeNode> res){
        if(root==p) {
            res.add(root);
            return true;
        }
        
        res.add(root);
        boolean found = false;
        found = findpath(root.left, p, res);
        found = findpath(root.right, p, res);
        if(!found) res.remove(res.size()-1);
        return found;
        
        
    }
    //找出兩個path的最后一個公共的節點
    public TreeNode findlastcommonNode(List<TreeNode> path1,List<TreeNode> path2){
        TreeNode res = null;
        int i=0;
        while(i<path1.size()&&i<path2.size()){
            if(path1.get(i)==path2.get(i))
                res = path1.get(i);
            i++;
        }
        
        return res;
    }

 

//如果只是普通的樹  不一定是二叉樹 但是節點中有指向父節點的指針。這樣將問題轉化為兩個鏈表的第一個交點。

 

貼一下此博主的解法:

http://blog.csdn.net/xyzbaihaiping/article/details/52122885

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM