給定一個(gè)二叉樹(shù), 找到該樹(shù)中兩個(gè)指定節(jié)點(diǎn)的最近公共祖先嘶朱。
百度百科中最近公共祖先的定義為:“對(duì)于有根樹(shù) T 的兩個(gè)結(jié)點(diǎn) p怕篷、q移必,最近公共祖先表示為一個(gè)結(jié)點(diǎn) x,滿足 x 是 p忧设、q 的祖先且 x 的深度盡可能大(一個(gè)節(jié)點(diǎn)也可以是它自己的祖先)∩缤矗”
例如见转,給定如下二叉樹(shù): 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
解釋: 節(jié)點(diǎn) 5 和節(jié)點(diǎn) 1 的最近公共祖先是節(jié)點(diǎn) 3。
示例 2:
輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節(jié)點(diǎn) 5 和節(jié)點(diǎn) 4 的最近公共祖先是節(jié)點(diǎn) 5蒜哀。因?yàn)楦鶕?jù)定義最近公共祖先節(jié)點(diǎn)可以為節(jié)點(diǎn)本身斩箫。
說(shuō)明:
所有節(jié)點(diǎn)的值都是唯一的。
p撵儿、q 為不同節(jié)點(diǎn)且均存在于給定的二叉樹(shù)中乘客。
來(lái)源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系官方授權(quán)淀歇,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處易核。
算法
Java
- 遞歸
參考題解:鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/
若 root 是 p, q 的 最近公共祖先 ,則只可能為以下情況之一:
p 和 q 在 root 的子樹(shù)中浪默,且分列 root 的 異側(cè)(即分別在左牡直、右子樹(shù)中);
p = root纳决,且 q 在 root 的左或右子樹(shù)中碰逸;
q = root ,且 p 在 root 的左或右子樹(shù)中阔加;
/**
* 遞歸
* 參考題解:鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/
* 若 root 是 p, q 的 最近公共祖先 饵史,則只可能為以下情況之一:
p 和 q 在 root 的子樹(shù)中,且分列 root 的 異側(cè)(即分別在左胜榔、右子樹(shù)中)胳喷;
p = root,且 q 在 root 的左或右子樹(shù)中夭织;
q = root 吭露,且 p 在 root 的左或右子樹(shù)中;
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// root 為null 或者 p尊惰、q 是 root
if (root == null || q == root || p == root) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 左邊為null奴饮,共同祖先節(jié)點(diǎn)在右側(cè)
if (left == null) {
return right;
}
// 右邊為null纬向,共同祖先節(jié)點(diǎn)在左側(cè)
if (right == null) {
return left;
}
return root;
}
- 緩存父節(jié)點(diǎn)
參考題解:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/
從上向下遍歷所有的父節(jié)點(diǎn),將父節(jié)點(diǎn)保存到哈希表中
從p節(jié)點(diǎn)向上查詢它的父節(jié)點(diǎn)戴卜,保存到臨時(shí)數(shù)組中逾条,判斷臨時(shí)數(shù)組中是否包含q節(jié)點(diǎn)
Map<Integer, TreeNode> map = new HashMap<>();
Set<Integer> visited = new HashSet<>();
/**
* 參考題解:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/
* 從上向下遍歷所有的父節(jié)點(diǎn),將父節(jié)點(diǎn)保存到哈希表中
* 從p節(jié)點(diǎn)向上查詢它的父節(jié)點(diǎn)投剥,保存到臨時(shí)數(shù)組中师脂,判斷臨時(shí)數(shù)組中是否包含q節(jié)點(diǎn)
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
dfs(root);
// 從p節(jié)點(diǎn)向上訪問(wèn)所有的父節(jié)點(diǎn)
while (p != null) {
visited.add(p.val);
p = map.get(p.val);
}
// 從q節(jié)點(diǎn)向上訪問(wèn)所有的父節(jié)點(diǎn)
while (q != null) {
// 判斷p的父節(jié)點(diǎn)是否包含q的父節(jié)點(diǎn)
if (visited.contains(q.val)) {
return q;
}
q = map.get(q.val);
}
return null;
}
/**
* 遞歸遍歷父節(jié)點(diǎn)
* @param node
*/
public void dfs(TreeNode node) {
if (node.left != null) {
map.put(node.left.val, node);
dfs(node.left);
}
if (node.right != null) {
map.put(node.right.val, node);
dfs(node.right);
}
}
swift
- 遞歸
/**
遞歸
*/
func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
// 如果root為nil余爆、p 為 root织盼、q為root,則共同祖先節(jié)點(diǎn)為root
if root == nil || p?.val == root?.val || q?.val == root?.val {
return root
}
// 遞歸左右子樹(shù)
let left = lowestCommonAncestor(root?.left, p, q)
let right = lowestCommonAncestor(root?.right, p, q)
// 左子樹(shù)為nil阀蒂,則祖先節(jié)點(diǎn)在右子樹(shù)中
if left == nil {
return right
}
// 右子樹(shù)為nil啄育,則祖先節(jié)點(diǎn)在左子樹(shù)中
if right == nil {
return left
}
return root
}
- 存儲(chǔ)父節(jié)點(diǎn)
class Solution {
// 父節(jié)點(diǎn)字典
var dict = [Int: TreeNode]()
// 已訪問(wèn)節(jié)點(diǎn)數(shù)組
var visited = [TreeNode]()
/**
從上到下遍歷父節(jié)點(diǎn)酌心,保存所有的父節(jié)點(diǎn)到字典中
*/
func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
dfs(root)
// 從p節(jié)點(diǎn)想上訪問(wèn)其所有的父節(jié)點(diǎn),保存到已訪問(wèn)數(shù)組中
var p = p
while p != nil {
visited.append(p!)
// 移動(dòng)到p的父節(jié)點(diǎn)
p = dict[p!.val]
}
var q = q
while q != nil {
if visited.contains(where: { (node) -> Bool in
return q!.val == node.val
}) {
return q
}
q = dict[q!.val]
}
return nil
}
func dfs(_ node: TreeNode?) {
if node?.left != nil {
dict[node!.left!.val] = node
dfs(node?.left)
}
if node?.right != nil {
dict[node!.right!.val] = node
dfs(node?.right)
}
}
}
GitHub:https://github.com/huxq-coder/LeetCode
歡迎star