题解:
思路一:
- 我们使用 HashMap 来存储,子节点的值 -> 父节点。
- dfs二叉树,构建map,保存每个节点对应的父节点
- 根据map,分别获得传入两个节点的祖先节点数组
- 查询这两个祖先节点数组的最近的公共元素
- 将一个数组转为set
- 从 0开始遍历第二个数组,找到第一个set中也包含的,就是最终结果。
代码如下:
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
|
// 保存 <值 , 父节点>
HashMap<Integer, TreeNode> hashMap;
public void dfs(TreeNode node ,TreeNode parent){
if (node == null) return;
hashMap.put(node.val,parent);
dfs(node.left,node);
dfs(node.right,node);
}
public List getParents(TreeNode node){
List<TreeNode> plist = new LinkedList<>();
TreeNode pnode = node;
while (pnode != null){
plist.add(pnode);
pnode = hashMap.get(pnode.val);
}
return plist;
}
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == null || q == null) return null;
hashMap = new HashMap<>();
// 处理 父节点 字典
dfs(root,null);
// p 的所有父节点
List<TreeNode> plist = getParents(p);
// q 的所有父节点
List<TreeNode> qlist = getParents(q);
HashSet set = new HashSet(plist);
for (int i = 0; i < qlist.size(); i++) {
if (set.contains(qlist.get(i)))
return qlist.get(i);
}
return null;
}
|
时间复杂度 : O(N)
空间复杂度 ; O(N)
优化:
思路二:
上述解题过程中, 发现我们完全没有用到 二叉搜索树 特殊的性质,时间复杂度比较高,由上图可以看出,虽然算法通过,但是执行效率非常差。 接下来,我们尝试优化。
- 发现二叉搜索树的最近公共祖先节点,总是在传入两个节点值之间(比如,上图中0, 4的最近公共祖先是 2。 4和7的最近公共祖先是6。)
- 当root.val 比两者都大时,则在左子树中查找
- 当root.val 比两者都小时,则在右子树中查找
- 否则,在两者之间,就是最近公共祖先节点
递归:
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == null || q == null) return null;
if (root.val > q.val && root.val > p.val){
return lowestCommonAncestor(root.left,p,q);
}else if (root.val < q.val && root.val < p.val){
return lowestCommonAncestor(root.right,p,q);
}
return root;
}
|
思路三:
迭代
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || p == null || q == null) return null;
while (root != null) {
if (root.val > q.val && root.val > p.val) {
root = root.left;
} else if (root.val < q.val && root.val < q.val) {
root = root.right;
} else {
return root;
}
}
return null;
}
|