1. 程式人生 > >劍指Offer(第二版)面試案例:樹中兩個節點的最低公共祖先節點

劍指Offer(第二版)面試案例:樹中兩個節點的最低公共祖先節點

劍指Offer(第二版)面試案例:樹中兩個節點的最低公共祖先節點

題目:輸入兩個樹節點,求它們的最低公共祖先節點。

反問:這棵樹是不是二叉樹?

面試官:是二叉樹,並且是二叉搜尋樹。

思路:

二叉搜尋樹是經過排序的,位於左子樹的節點都比父節點小,位於右子樹的節點都比父節點大。既然要找最低的公共祖先節點,我們可以從根節點開始進行比較。

若當前節點的值比兩個節點的值都大,那麼最低的祖先節點一定在當前節點的左子樹中,則遍歷當前節點的左子節點;

反之,若當前節點的值比兩個節點的值都小,那麼最低的祖先節點一定在當前節點的右子樹中,則遍歷當前節點的右子節點;

這樣,直到找到一個節點,位於兩個節點值的中間,則找到了最低的公共祖先節點。


/**
 * 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;
        if(root.val>p.val&&root.val>q.val)
            return lowestCommonAncestor(root.left,p,q);
        if(root.val<p.val&&root.val<q.val)
            return lowestCommonAncestor(root.right,p,q);
        else
            return root;
    }
}

面試官:如果只是普通的二叉樹呢?

反問:樹的節點中有沒有指向父節點的指標?

面試官:為什麼需要指向父節點的指標?

答:如果存在parent指標,則分別從輸入的p節點和q節點指向root根節點,其實這就是兩個單鏈表。問題轉化為求兩個單鏈表相交的第一個公共節點

面試官:那如果不存在parent指標呢?

遞迴的解法如下:

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) 
            return right;
        if (right == null) 
            return left;
        return root;
    }
迭代解法:

需要我們儲存下由root根節點到p和q節點的路徑,並且將路徑存入list中,則問題轉化為求兩個list集合的最後一個共同元素。

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {  
        if(root==null || p==null || q==null) 
        	return null;
        List<TreeNode> pathp = new ArrayList<>();  
        List<TreeNode> pathq = new ArrayList<>();  
        pathp.add(root);  
        pathq.add(root);  
          
        getPath(root, p, pathp);  
        getPath(root, q, pathq);  
          
        TreeNode lca = null;  
        for(int i=0; i<pathp.size() && i<pathq.size(); i++) {  
            if(pathp.get(i) == pathq.get(i)) 
            	lca = pathp.get(i);  
            else 
            	break;  
        }  
        return lca;  
    }  
      
    private boolean getPath(TreeNode root, TreeNode n, List<TreeNode> path) {  
        if(root==n)   
            return true;  
        
        if(root.left!=null) {  
            path.add(root.left);  
            if(getPath(root.left, n, path))
            	return true;  
            path.remove(path.size()-1);  
        }  
          
        if(root.right!=null) {  
            path.add(root.right);  
            if(getPath(root.right, n, path)) 
            	return true;  
            path.remove(path.size()-1);  
        }  
        return false;  
    }

該題是網際網路面試中出現頻率賊高的二叉樹題目。必須掌握哦~

如果對你有幫助,記得點贊哦~歡迎大家關注我的部落格,可以進群366533258一起交流學習哦~

本群給大家提供一個學習交流的平臺,內設菜鳥Java管理員一枚、精通演算法的金牌講師一枚、一枚、藍芽BlueTooth管理員一枚、Web前端管理一枚以及C#管理一枚。歡迎大家進來交流技術。