每日一題 - 劍指 Offer 68 - II. 二叉樹的最近公共祖先
阿新 • • 發佈:2020-07-18
題目資訊
-
時間: 2019-07-07
-
題目連結:Leetcode
-
tag:二叉樹 遞迴 深度優先搜尋
-
難易程度:中等
-
題目描述:
給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。
百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x 的深度儘可能大(一個節點也可以是它自己的祖先)。”
例如,給定如下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]
3 / \ 5 1 / \ / \ 6 2 0 8 / \ 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。因為根據定義最近公共祖先節點可以為節點本身。
注意
1. 所有節點的值都是唯一的。
2. p、q 為不同節點且均存在於給定的二叉樹中。
解題思路
本題難點
一般二叉樹查詢最近公共祖先節點。
具體思路
考慮通過遞迴對二叉樹進行後序遍歷,當遇到節點 p 或 q 時返回。從底至頂回溯,當節點 p,q 在節點 root 的異側時,節點 root 即為最近公共祖先,則向上返回 root 。
遞推工作:
- 遞迴左子節點,返回值記為 left ;
- 遞迴右子節點,返回值記為 right ;
返回值:
- 當 left 和 right 同時為空 :說明 root 的左 / 右子樹中都不包含 p,q ,返回 null ;
- 當 left 和 right 同時不為空 :說明 p,q 分列在 root 的 異側 (分別在 左 / 右子樹),因此 root 為最近公共祖先,返回 root ;
- 當 left 為空 ,right 不為空 :p,q 都不在 root 的左子樹中,直接返回 right 。具體可分為兩種情況:
- p,q 其中一個在 root的 右子樹 中,此時 right 指向 p(假設為 p );
- p,q 兩節點都在 root 的 右子樹 中,此時的 right 指向 最近公共祖先節點 ;
- 當 left 不為空 , right為空 :p,q 都不在 root 的右子樹中,直接返回 left 。具體可分為兩種情況
- p,q 其中一個在 root的 左子樹 中,此時 left 指向 p(假設為 p );
- p,q 兩節點都在 root 的 左子樹 中,此時的 left 指向 最近公共祖先節點 ;
提示
程式碼
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//當 root 等於 p,q ,則直接返回 root
if(root == null || root.val == p.val || root.val == q.val){
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;
}
}
複雜度分析:
- 時間複雜度 O(N) : 其中 N為二叉樹節點數;最差情況下,需要遞迴遍歷樹的所有節點。
- 空間複雜度 O(N) : 最差情況下,遞迴深度達到 N,系統使用 O(N)大小的額外空間。