package problems.medium;
import problems.utils.TreeNode;
import java.util.*;
/**
* Created by sherxon on 3/2/17.
*/
public class LowestCommonAncestorofaBinaryTree {
/**
* We first find path from root to p and from root to q nodes.
* Then we traverse both paths till the values in arrays are same.
* Return the common element just before the mismatch.
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) return null;
Map<TreeNode, TreeNode> map = bfs(root);
LinkedList<TreeNode> pPath = new LinkedList<>();
TreeNode pp = p;
while (pp != null) {
pPath.addFirst(pp);
pp = map.get(pp);
}
LinkedList<TreeNode> qPath = new LinkedList<>();
TreeNode qq = q;
while (qq != null) {
qPath.addFirst(qq);
qq = map.get(qq);
}
ListIterator<TreeNode> pit = pPath.listIterator();
ListIterator<TreeNode> qit = qPath.listIterator();
while (pit.hasNext() || qit.hasNext()) {
if (!pit.hasNext()) return pit.previous();
if (!qit.hasNext()) return qit.previous();
TreeNode pcurrent = pit.next();
TreeNode qcurrent = qit.next();
if (pcurrent != qcurrent) return map.get(pcurrent);
}
return root;
}
Map<TreeNode, TreeNode> bfs(TreeNode x) {
Queue<TreeNode> q = new LinkedList<>();
q.add(x);
Map<TreeNode, TreeNode> map = new HashMap<>();
map.put(x, null);
while (!q.isEmpty()) {
TreeNode xx = q.remove();
if (xx.left != null) {
q.add(xx.left);
map.put(xx.left, xx);
}
if (xx.right != null) {
q.add(xx.right);
map.put(xx.right, xx);
}
}
return map;
}
}