1. 程式人生 > >LeetCode-236 lowest common ancestor of a binary tree 二叉樹的最近公共祖先

LeetCode-236 lowest common ancestor of a binary tree 二叉樹的最近公共祖先

題目連結

https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

題意

        中文題,就是給出一個一般的二叉樹,求其最近公共祖先,並且宣告節點A是本節點的祖先。

題解

        算是“二叉搜尋樹的最近公共祖先”問題的升級版,但是仍然沒有比較使用LCA演算法。可以利用二叉樹的性質,利用DFS的方法來求解。仍然分析公共祖先與根root的關係,總共有3種:

1.在root的左子樹

2.在root的右子樹

3.root本身

因為結點本身就是該結點的祖先,所以3的情況是存在的。那麼我們可以先判定一下root本身:

if(root == null) return null;
if(root == p || root == q) return root;

如果是空,那就直接返回null,如果是搜尋的一個結點,因為本身也是祖先,所以需要返回root。

        那麼在遞迴的時候,就能判定出兩個結點分別的最近公共祖先。這樣,如果我們回溯的時候返回null或者root,那麼回溯的上一層,一定存在這樣的四種情況:

1.沒有遞迴,直接返回root。

2.left回溯回來了一個值,而right為null。

3.right回溯回來了一個值,而left為null。

4.left與right都回溯回來了一個值。

對於1,就沒啥好說了,沒有再搜尋下去的必要,就算其子孫有一個為另一個結點,那該該節點就是正確答案。對於4,說明節點相對於root分散在兩個子樹,那麼該結點就是答案了,因為是回溯,這個就是最近公共祖先。對於2、3實際上是一種類似的情況,root的一個子樹上有需要找的結點,那麼此時存在兩種可能:

1.另一個結點也在該子樹上

2.另一個結點在其他兄弟或者祖先的兄弟上

那麼實際上解決方法都是向上回溯該結點,因為如果是情況1,這個結點就是答案了,如果是情況2,那麼就繼續向上回溯,直到碰見有一個結點滿足情況4。

        是有一點繞了,其實直接裸奔LCA應該也是沒什麼問題的。這樣程式碼更簡單一點。

Java 程式碼

class Solution {    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(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 ? right : left;
    }
}