算法學習之樹中兩個節點的最低公共祖先

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

普通的樹:

1、我們使用兩個LinkedList依次記錄從根節點到兩個給定節點的路徑

2、得到路徑後,我們對兩個路徑進行比較,最後一個相等的節點即爲所求(添加與取得順序相反,所以最後一個爲最低公共節點)

  public TreeNode getLastCommonParent(TreeNode root, TreeNode p1, TreeNode p2) {
        if (root == null || p1 == null || p2 == null) return null;
        LinkedList<TreeNode> path1 = new LinkedList<>();
        LinkedList<TreeNode> path2 = new LinkedList<>();
        LinkedList<TreeNode> tem = new LinkedList<>();
        getNodePath(root, p1, tem, path1);
        getNodePath(root, p2, tem, path2);

        if (path1.size() <= 0 || path2.size() <= 0) return null;
        return getCommon(path1, path2);
    }
    // 比較兩個path,得到最後一個相同節點,即我們的目標值
    private TreeNode getCommon(LinkedList<TreeNode> path1, LinkedList<TreeNode> path2) {
        TreeNode temNode = null;
        for (int i = 0; i < path1.size(); i++) {
            if (path1.get(i) != path2.get(i)) {
                break;
            }
            temNode = path1.get(i);
        }
        return temNode;

    }
    // 獲取
    private void getNodePath(TreeNode root, TreeNode targeNode, LinkedList<TreeNode> tem, LinkedList<TreeNode> path) {
        if (root == targeNode) {
            return;
        }
        tem.add(root);
        List<TreeNode> children = root.children; // 獲取左右兩個子節點,可能只存在一個,或者0個
        for (TreeNode node : children) { 
            if (node == targeNode) {
                path.addAll(tem);
                break;
            }
            getNodePath(node, targeNode, tem, path);
        }
        tem.removeLast(); // 避免重複添加,刪除掉(因爲遞歸的性質,到達底層時,回溯時依次刪除)
    }
public class TreeNode {

    public List<TreeNode> children = new ArrayList<>();
    int val;

    TreeNode(int x) {
        val = x;
    }
}
        // 測試數據
        val n1 = TreeNode(1)
        val n2 = TreeNode(2)
        val n3 = TreeNode(3)
        val n4 = TreeNode(4)
        val n5 = TreeNode(5)
        val n6 = TreeNode(6)
        val n7 = TreeNode(7)
        val n8 = TreeNode(8)
        val n9 = TreeNode(9)
        val n10 = TreeNode(10)

        n1.children.add(n2)
        n1.children.add(n3)
        n2.children.add(n4)
        n4.children.add(n6)
        n4.children.add(n7)
        n3.children.add(n5)
        n5.children.add(n8)
        n5.children.add(n9)
        n5.children.add(n10)

        

 

時間複雜度:O(n)

空間複雜度:O(logn)

其實還有另外的情況:如該樹爲普通二叉樹

    /**
     * 遞歸,找到兩個目標節點
      * @param root
     * @param left1
     * @param right1
     * @return
     */
    public TreeNode getLastCommonParent2(TreeNode root,TreeNode left1,TreeNode right1){

        if(root==null||root==left1||root==right1) {
            return root;
        }
        // 遞歸是一個大過程,回溯時,左子樹的右小枝也被算作大枝中的左枝
        TreeNode left = getLastCommonParent2(root.left,left1,right1);
        TreeNode right = getLastCommonParent2(root.right,left1,right1);
        // 直到左右都不爲null返回的root纔是我們所求否則目標值爲null
        return left==null?right1:right==null?left:root;
        // 等同於
//        if(left==null) {
//            return right;
//        }else {
//            if(right==null) {
//                return left;
//            }else {
//                return root;
//            }
//        }
    }

解法比較簡單其他的情況如此樹爲二叉搜索樹這裏就不贅述了,可以參考下我找到的這篇文章

點這裏

 

發佈了94 篇原創文章 · 獲贊 8 · 訪問量 5127
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章