package com.interview.books.topcoder.tree;
import com.interview.basics.search.SegmentTree;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created_By: stefanie
* Date: 15-1-19
* Time: 下午8:27
*
*
*/
class GenericTreeNode<T>{
T val;
List<GenericTreeNode> children = new ArrayList();
public GenericTreeNode(T val){
this.val = val;
}
}
public class TCT_T1_LowestCommonAncestor<T> {
/**
*
* E[1, 2*N-1] - the nodes visited in an Euler Tour of T; E[i] is the label of i-th visited node in the tour.
* L[1, 2*N-1] - the levels of the nodes visited in the Euler Tour; L[i] is the level of node E[i].
* H[1, N] - H[i] is the index of the first occurrence of node i in E (any occurrence would be good, so it's not bad if we consider the first one)
*
* The whole process is like this:
* 1. build the 3 arrays: E, L and H
* 2. for any two nodes u and v, find the H[u] and H[v], do RMQ in L of range(H[u], H[v]), assume the found index is t, return E[t] as the parent.
*/
int N;
T[] E;
Integer[] L;
Map<T, Integer> H;
SegmentTree<Integer> tree;
int idx;
public TCT_T1_LowestCommonAncestor(GenericTreeNode<T> root, int nodeNum){
this.N = nodeNum;
E = (T[]) new Object[2 * N - 1];
L = new Integer[2 * N - 1];
H = new HashMap();
idx = -1;
eulerTour(root, 1);
tree = new SegmentTree(L, new SegmentTree.Operator<Integer>() {
@Override
public Integer operate(Integer a, Integer b) {
if(L[a] <= L[b]) return a;
else return b;
}
@Override
public Integer init(int idx, Integer[] input) {
return idx;
}
});
}
private void eulerTour(GenericTreeNode<T> node, int level){
if(node == null) return;
idx++;
E[idx] = node.val;
L[idx] = level;
H.put(node.val, idx);
for(GenericTreeNode child : node.children) {
eulerTour(child, level + 1);
idx++;
E[idx] = node.val;
L[idx] = level;
}
}
public T LCA(T node1, T node2){
int idx1 = H.get(node1);
int idx2 = H.get(node2);
int parentIdx = tree.query(Math.min(idx1, idx2), Math.max(idx1, idx2));
return E[parentIdx];
}
public static void main(String[] args){
GenericTreeNode<Integer>[] nodes = new GenericTreeNode[14];
for(int i = 1; i < 14; i++) nodes[i] = new GenericTreeNode(i);
nodes[1].children.add(nodes[2]);
nodes[1].children.add(nodes[3]);
nodes[1].children.add(nodes[4]);
nodes[3].children.add(nodes[5]);
nodes[3].children.add(nodes[6]);
nodes[3].children.add(nodes[7]);
nodes[6].children.add(nodes[8]);
nodes[6].children.add(nodes[9]);
nodes[7].children.add(nodes[10]);
nodes[7].children.add(nodes[11]);
nodes[10].children.add(nodes[12]);
nodes[10].children.add(nodes[13]);
TCT_T1_LowestCommonAncestor<Integer> finder = new TCT_T1_LowestCommonAncestor(nodes[1], 13);
System.out.println(finder.LCA(9, 12)); //3
System.out.println(finder.LCA(2, 11)); //3
}
}