非递归写法:
a) 从两个节点往上找,一直走到根节点,那么根节点到这两个节点的连线相交的地方,即为两节点的最近公共祖先。
b)从根节点往下找,最后一次相交的地方,即为两节点的最近公共祖先。
6 和 7 公共祖先有 5 和 3。
使用深度优先搜索(dfs)
使用层序遍历(BFS)
比如 2 和 8,遍历到第三层就不用往下遍历了
public int lowestCommonAncestor(TreeNode root, int o1, int o2) {
//记录遍历到的每个节点的父节点。
Map<Integer, Integer> parent = new HashMap<>();
Queue<TreeNode> queue = new LinkedList<>();
parent.put(root.val, Integer.MIN_VALUE);//根节点没有父节点,给他默认一个值
queue.add(root);
//直到两个节点都找到为止。
while (!parent.containsKey(o1) || !parent.containsKey(o2)) {
//队列是一边进一边出,这里poll方法是出队,
TreeNode node = queue.poll();
if (node.left != null) {
//左子节点不为空,记录下他的父节点
parent.put(node.left.val, node.val);
//左子节点不为空,把它加入到队列中
queue.add(node.left);
}
//右节点同上
if (node.right != null) {
parent.put(node.right.val, node.val);
queue.add(node.right);
}
}
Set<Integer> ancestors = new HashSet<>();
//记录下o1和他的祖先节点,从o1节点开始一直到根节点。
while (parent.containsKey(o1)) {
ancestors.add(o1);
o1 = parent.get(o1);
}
//查看o1和他的祖先节点是否包含o2节点,如果不包含再看是否包含o2的父节点……
while (!ancestors.contains(o2))
o2 = parent.get(o2);
return o2;
}
递归写法:
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
return helper(root, o1, o2).val;
}
public TreeNode helper(TreeNode root, int o1, int o2) {
if (root == null || root.val == o1 || root.val == o2) {
return root;
}
TreeNode left = helper(root.left, o1, o2);
TreeNode right = helper(root.right, o1, o2);
//如果 left 为空,说明这两个节点在 root 结点的右子树上,只需返回右子树查找的结果即可
if (left == null) {
return right;
}
if (right == null) {
return left;
}
//如果 left 和 right 都不为空,说明这两个结点一个在左子树,一个在右子树
//只需返回 cur 即可
return root;
}