题目描述:
给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。
数据范围:1 \le n \le 10001≤n≤1000,树上每个节点的val满足 0<val \le 1000<val≤100
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
注:本题保证二叉树中每个节点的val值均不相同。
如当输入[3,5,1,6,2,0,8,#,#,7,4],5,1时,二叉树{3,5,1,6,2,0,8,#,#,7,4}如下图所示:
对于该题,我们可以使用HashMap对数据进行存储,在存储时因为题目需要找到公共祖先,所以我们可以对key-value->赋值为 该节点的值-父节点的值。然后对树进行层序遍历,通过层序遍历和HashMap的配合将树的结点都记录下来,但是我们只需要找到o1和o2两个值对应结点的公共祖先结点,所以我们并不需要将整个树都记录下来,所以我们的终止条件就是当HashMap中已经存储了key(o1)和key(o2)。
截止现在,我们已经在map中存储了包含o1和o2值的结点,那么在接下来我们需要去寻找o1和o2和公共祖先。在map中我们已经存储了o1和o2的祖先结点值,所以接下来我们只需要将其中o1或者o2其中一个的所有祖先结点值记录下来,然后再拿o2的祖先结点值和o1的所有祖先结点值作比较,如果o2的某个祖先结点值和o1中的某个祖先结点值相同,那么此时o2的值就是他们公共祖先结点的值,该结点就是最近的公共祖先结点。
具体的代码实现如下:
public int find(TreeNode root, int o1, int o2) {
HashMap<Integer,Integer> map = new HashMap<>();
LinkedList<TreeNode> list = new LinkedList<>();
list.offer(root);
map.put(root.val,-1);
while(!map.containsKey(o1) || !map.containsKey(o2)){
TreeNode node = list.poll();
if(node.left != null){
list.offer(node.left);
map.put(node.left.val,node.val);
}
if(node.right != null){
list.offer(node.right);
map.put(node.right.val,node.val);
}
}
HashSet<Integer> set = new HashSet<>();
while(map.containsKey(o1)){
set.add(o1);
o1 = map.get(o1);
}
while(!set.contains(o2)){
o2 = map.get(o2);
}
return o2;