《劍指offer》二叉樹的最近公共祖先--遞歸解決

0x01.問題

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義爲:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]

在這裏插入圖片描述

示例 1:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。

示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節點 5 和節點 4 的最近公共祖先是節點 5。因爲根據定義最近公共祖先節點可以爲節點本身。

說明:

  • 所有節點的值都是唯一的。
  • p、q 爲不同節點且均存在於給定的二叉樹中。

0x02.分析思路

讀懂題目,明確公共祖先的概念,公共祖先root應該有以下幾種可能。

  • pq位於root的兩側(也就是說pqroot的子樹,且在不同側)
  • root=pq位於root的左子樹或者右子樹。
  • root=qp位於root的左子樹或者右子樹。

接下來就是如何去尋找最近的公共祖先了,最近,也就是深度最大的公共祖先,這就暗示着我們,如果從葉子節點開始尋找,那麼,找到的第一個,就是最近的,這種尋找的方式,其實也就是後序遍歷的方法。

假設,我們通過後序遍歷的方式找到了最近的,如何確保在後面的遞歸步驟中不會更新呢?

  • 很簡單,在找到第一個公共祖先後,後面找到的公共祖先都不可能滿足這個條件,因爲這個最近的公共祖先也成爲別人的子樹時,對於其它的公共祖先,就不可能滿足上述條件了,即pq已經在一側了。

具體算法思路:

  • 核心判斷語句:( lcontain && rcontain )||((root==p || root==q)&&(lcontain||rcontain)).

    • lcontain代表,左子樹存在pq
    • rcontain代表,右子樹存在pq
  • 尋找方式採用後序的方式,從葉子節點到根節點。

具體代碼如下:

0x03.解決代碼–遞歸

class Solution {
    private TreeNode ans;
    private Boolean dfs(TreeNode root,TreeNode p,TreeNode q){
        if(root==null){
            return false;
        }
        Boolean lcontain=dfs(root.left,p,q);
        Boolean rcontain=dfs(root.right,p,q);
        if((lcontain&&rcontain)||(root.val==p.val||root.val==q.val)&&(lcontain||rcontain)){
            ans=root;
        }
        return lcontain||rcontain||(root.val==p.val||root.val==q.val);
    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root,p,q);
        return ans;
    }
}

ATFWUS --Writing By 2020–05-11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章