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
應該有以下幾種可能。
p
,q
位於root
的兩側(也就是說p
,q
是root
的子樹,且在不同側)root=p
,q
位於root
的左子樹或者右子樹。root=q
,p
位於root
的左子樹或者右子樹。
接下來就是如何去尋找最近的公共祖先了,最近,也就是深度最大的公共祖先,這就暗示着我們,如果從葉子節點開始尋找,那麼,找到的第一個,就是最近的,這種尋找的方式,其實也就是後序遍歷的方法。
假設,我們通過後序遍歷的方式找到了最近的,如何確保在後面的遞歸步驟中不會更新呢?
- 很簡單,在找到第一個公共祖先後,後面找到的公共祖先都不可能滿足這個條件,因爲這個最近的公共祖先也成爲別人的子樹時,對於其它的公共祖先,就不可能滿足上述條件了,即
p
,q
已經在一側了。
具體算法思路:
-
核心判斷語句:
( lcontain && rcontain )||((root==p || root==q)&&(lcontain||rcontain))
.lcontain
代表,左子樹存在p
或q
。rcontain
代表,右子樹存在p
或q
。
-
尋找方式採用後序的方式,從葉子節點到根節點。
具體代碼如下:
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