dcddc

西米大人的博客

0%

最近公共祖先

题目描述

给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。
最近公共祖先是两个节点的公共的祖先节点且具有最大深度。
例子:对于下面这棵二叉树

1
2
3
4
5
  4
/ \
3 7
/ \
5 6

LCA(3, 5) = 4
LCA(5, 6) = 7
LCA(6, 7) = 7

思路

注意:这里是二叉树,并非二叉查找树!
在二叉树中递归查找这两个元素的过程中,将这两个元素路径上的父节点都加入到两个list中
从头访问list元素较少的那个list,判断其元素是否存在于另一个list中,存在即找到公共祖先,不存在则没有公共祖先
如何将元素所有的祖先都加入到list且是按照由近祖先到远祖先的顺序?
1、从二叉树的根节点开始,判断当前节点是否为tar,是则添加到list里,返回true
2、当前节点 != tar,递归左子树,并判断递归函数返回的结果:
i、如果为true,表示找到tar了,将当前结点加入到list,返回true,因为当前节点就是祖先!
ii、如果为false,表示没找到tar,则递归右子树,并判断递归函数返回的结果,判断的处理逻辑同上!

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
// exp
if(A.val == root.val || B.val == root.val) {
return root;
}
// init stack to hold father
ArrayList<TreeNode> listA = new ArrayList<>();
ArrayList<TreeNode> listB = new ArrayList<>();

// find A
findLoc(root, A, listA);
findLoc(root, B, listB);

// find common root
if(listA.size() < listB.size()) {
for(int i = 0; i < listA.size(); i++) {
if(listB.contains(listA.get(i))) {
return listA.get(i);
}
}
return null;
}else {
for(int i = 0; i < listB.size(); i++) {
if(listA.contains(listB.get(i))) {
return listB.get(i);
}
}
return null;
}
}

// 当前节点找不到,找左子树,左子树找不到,找右子树
private boolean findLoc(TreeNode root, TreeNode tar, ArrayList<TreeNode> list) {
if(root == null) {
return false;
}
if(root.val == tar.val) {
list.add(root);
return true;
}
if(!findLoc(root.left, tar, list)) { // 当前节点未找到,且左子树没找到
if(findLoc(root.right, tar, list)) { // 右子树找到了
list.add(root);
return true;
}else { // 右子树没找到
return false;
}
}else { // 当前节点没找到,左子树找到了
list.add(root);
return true;
}

}

考察点

  • 二叉树