import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
static class Node {
List<Node> children = new ArrayList<Node>();
this.id = id;
}
return id.toString();
}
}
//test data
Node root = new Node(0);
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n1a = new Node(11);
Node n1b = new Node(12);
Node n3a = new Node(31);
Node n3b = new Node(32);
Node n3c = new Node(33);
//connections
root.children.add(n1);
root.children.add(n2);
root.children.add(n3);
n1.children.add(n1a);
n1.children.add(n1b);
n3.children.add(n3a);
n3.children.add(n3b);
n3.children.add(n3c);
//tests
System.
out.
println("### Test 1 ###"); Node r = findClosestCommonAncestor(root, n1b, n3a);
System.
out.
println("Expected: " + root
); System.
out.
println("Result: " + r
); System.
out.
println("Passed --> " + (r
== root
));
System.
out.
println("### Test 2 ###"); r = findClosestCommonAncestor(root, n3, n3b);
System.
out.
println("Expected: " + n3
); System.
out.
println("Result: " + r
); System.
out.
println("Passed --> " + (r
== n3
));
System.
out.
println("### Test 3 ###"); r = findClosestCommonAncestor(root, n3a, n3c);
System.
out.
println("Expected: " + n3
); System.
out.
println("Result: " + r
); System.
out.
println("Passed --> " + (r
== n3
));
System.
out.
println("### Test 4 ###"); r = findClosestCommonAncestor(root, n2, n1a);
System.
out.
println("Expected: " + root
); System.
out.
println("Result: " + r
); System.
out.
println("Passed --> " + (r
== root
));
}
static Node findClosestCommonAncestor(Node node, Node p, Node q) {
Stack<Node> parentStack = new Stack<Node>();
Stack<Integer> childIndexStack = new Stack<Integer>();
Stack<Node> firstNodePath = null;
while (!parentStack.empty() || node != null) {
if (node != null) {
if (node == p || node == q) {
if (firstNodePath != null) {
parentStack.add(node);
int n
= Math.
min(parentStack.
size(), firstNodePath.
size()); for (int i = n - 1; i >= 0; i--) {
if (parentStack.get(i) == firstNodePath.get(i)) {
return parentStack.get(i);
}
}
return null;
} else {
firstNodePath = new Stack<Node>();
firstNodePath.setSize(parentStack.size());
firstNodePath.push(node);
}
}
if (!node.children.isEmpty()) {
parentStack.push(node);
childIndexStack.push(0);
node = node.children.get(0);
} else {
node = null;
}
} else {
node = parentStack.peek();
Integer i
= childIndexStack.
pop() + 1; if (i >= node.children.size()) {
node = null;
parentStack.pop();
} else {
node = node.children.get(i);
childIndexStack.push(i);
}
}
}
return null;
}
}
aW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5sYW5nLio7CmltcG9ydCBqYXZhLmlvLio7CgpjbGFzcyBJZGVvbmUgewoJCglzdGF0aWMgY2xhc3MgTm9kZSB7CgkJTGlzdDxOb2RlPiBjaGlsZHJlbiA9IG5ldyBBcnJheUxpc3Q8Tm9kZT4oKTsKCQlJbnRlZ2VyIGlkOwoJCU5vZGUoSW50ZWdlciBpZCkgewoJCQl0aGlzLmlkID0gaWQ7CgkJfQoJCXB1YmxpYyBTdHJpbmcgdG9TdHJpbmcoKSB7CgkJCXJldHVybiBpZC50b1N0cmluZygpOwoJCX0KCX0KCQoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4gKFN0cmluZ1tdIGFyZ3MpIHRocm93cyBqYXZhLmxhbmcuRXhjZXB0aW9uIHsKCQkKCQkvL3Rlc3QgZGF0YQoJCU5vZGUgcm9vdCA9IG5ldyBOb2RlKDApOwoJCU5vZGUgbjEgPSBuZXcgTm9kZSgxKTsKCQlOb2RlIG4yID0gbmV3IE5vZGUoMik7CgkJTm9kZSBuMyA9IG5ldyBOb2RlKDMpOwoJCU5vZGUgbjFhID0gbmV3IE5vZGUoMTEpOwoJCU5vZGUgbjFiID0gbmV3IE5vZGUoMTIpOwoJCU5vZGUgbjNhID0gbmV3IE5vZGUoMzEpOwoJCU5vZGUgbjNiID0gbmV3IE5vZGUoMzIpOwoJCU5vZGUgbjNjID0gbmV3IE5vZGUoMzMpOwoJCQoJCS8vY29ubmVjdGlvbnMKCQlyb290LmNoaWxkcmVuLmFkZChuMSk7CgkJcm9vdC5jaGlsZHJlbi5hZGQobjIpOwoJCXJvb3QuY2hpbGRyZW4uYWRkKG4zKTsKCQluMS5jaGlsZHJlbi5hZGQobjFhKTsKCQluMS5jaGlsZHJlbi5hZGQobjFiKTsKCQluMy5jaGlsZHJlbi5hZGQobjNhKTsKCQluMy5jaGlsZHJlbi5hZGQobjNiKTsKCQluMy5jaGlsZHJlbi5hZGQobjNjKTsKCQkKCQkvL3Rlc3RzCgkJU3lzdGVtLm91dC5wcmludGxuKCIjIyMgVGVzdCAxICMjIyIpOwoJCU5vZGUgciA9IGZpbmRDbG9zZXN0Q29tbW9uQW5jZXN0b3Iocm9vdCwgbjFiLCBuM2EpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiRXhwZWN0ZWQ6ICIgKyByb290KTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIlJlc3VsdDogIiArIHIpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiUGFzc2VkIC0tPiAiICsgKHIgPT0gcm9vdCkpOwoJCQoJCVN5c3RlbS5vdXQucHJpbnRsbigiIyMjIFRlc3QgMiAjIyMiKTsKCQlyID0gZmluZENsb3Nlc3RDb21tb25BbmNlc3Rvcihyb290LCBuMywgbjNiKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIkV4cGVjdGVkOiAiICsgbjMpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiUmVzdWx0OiAiICsgcik7CgkJU3lzdGVtLm91dC5wcmludGxuKCJQYXNzZWQgLS0+ICIgKyAociA9PSBuMykpOwoJCQoJCVN5c3RlbS5vdXQucHJpbnRsbigiIyMjIFRlc3QgMyAjIyMiKTsKCQlyID0gZmluZENsb3Nlc3RDb21tb25BbmNlc3Rvcihyb290LCBuM2EsIG4zYyk7CgkJU3lzdGVtLm91dC5wcmludGxuKCJFeHBlY3RlZDogIiArIG4zKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oIlJlc3VsdDogIiArIHIpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiUGFzc2VkIC0tPiAiICsgKHIgPT0gbjMpKTsKCQkKCQlTeXN0ZW0ub3V0LnByaW50bG4oIiMjIyBUZXN0IDQgIyMjIik7CgkJciA9IGZpbmRDbG9zZXN0Q29tbW9uQW5jZXN0b3Iocm9vdCwgbjIsIG4xYSk7CgkJU3lzdGVtLm91dC5wcmludGxuKCJFeHBlY3RlZDogIiArIHJvb3QpOwoJCVN5c3RlbS5vdXQucHJpbnRsbigiUmVzdWx0OiAiICsgcik7CgkJU3lzdGVtLm91dC5wcmludGxuKCJQYXNzZWQgLS0+ICIgKyAociA9PSByb290KSk7CgkJCgl9CgkKCXN0YXRpYyBOb2RlIGZpbmRDbG9zZXN0Q29tbW9uQW5jZXN0b3IoTm9kZSBub2RlLCBOb2RlIHAsIE5vZGUgcSkgewoJCQogICAgICAgIFN0YWNrPE5vZGU+IHBhcmVudFN0YWNrID0gbmV3IFN0YWNrPE5vZGU+KCk7CiAgICAgICAgU3RhY2s8SW50ZWdlcj4gY2hpbGRJbmRleFN0YWNrID0gbmV3IFN0YWNrPEludGVnZXI+KCk7CiAgICAgICAgU3RhY2s8Tm9kZT4gZmlyc3ROb2RlUGF0aCA9IG51bGw7CiAgICAgICAgd2hpbGUgKCFwYXJlbnRTdGFjay5lbXB0eSgpIHx8IG5vZGUgIT0gbnVsbCkgewoKICAgICAgICAJaWYgKG5vZGUgIT0gbnVsbCkgewogICAgICAgIAkJCiAgICAgICAgCQlpZiAobm9kZSA9PSBwIHx8IG5vZGUgPT0gcSkgewoKICAgICAgICAJCQlpZiAoZmlyc3ROb2RlUGF0aCAhPSBudWxsKSB7CiAgICAgICAgCQkJCXBhcmVudFN0YWNrLmFkZChub2RlKTsKICAgICAgICAJCQkJaW50IG4gPSBNYXRoLm1pbihwYXJlbnRTdGFjay5zaXplKCksIGZpcnN0Tm9kZVBhdGguc2l6ZSgpKTsKICAgICAgICAJCQkJZm9yIChpbnQgaSA9IG4gLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIAkJCQkJaWYgKHBhcmVudFN0YWNrLmdldChpKSA9PSBmaXJzdE5vZGVQYXRoLmdldChpKSkgewogICAgICAgIAkJCQkJCXJldHVybiBwYXJlbnRTdGFjay5nZXQoaSk7IAogICAgICAgIAkJCQkJfQoJCQkJCQl9CiAgICAgICAJCQkJCXJldHVybiBudWxsOwogICAgICAgIAkJCQkJCiAgICAgICAgCQkJfSBlbHNlIHsKICAgICAgICAJCQkJZmlyc3ROb2RlUGF0aCA9IG5ldyBTdGFjazxOb2RlPigpOwogICAgICAgIAkJCQlmaXJzdE5vZGVQYXRoLnNldFNpemUocGFyZW50U3RhY2suc2l6ZSgpKTsKICAgICAgICAJCQkJQ29sbGVjdGlvbnMuY29weShmaXJzdE5vZGVQYXRoLCBwYXJlbnRTdGFjayk7CiAgICAgICAgCQkJCWZpcnN0Tm9kZVBhdGgucHVzaChub2RlKTsKICAgICAgICAJCQl9CgogICAgICAgIAkJfQogICAgICAgIAkJCiAgICAgICAgCQlpZiAoIW5vZGUuY2hpbGRyZW4uaXNFbXB0eSgpKSB7CiAgICAgICAgCQkJcGFyZW50U3RhY2sucHVzaChub2RlKTsKICAgICAgICAJCQljaGlsZEluZGV4U3RhY2sucHVzaCgwKTsKICAgICAgICAJCQlub2RlID0gbm9kZS5jaGlsZHJlbi5nZXQoMCk7CiAgICAgICAgCQl9IGVsc2UgewogICAgICAgIAkJCW5vZGUgPSBudWxsOwogICAgICAgIAkJfQogICAgICAgIAkgICAgCiAgICAgICAgCX0gZWxzZSB7CiAgICAgICAgCQogICAgICAgIAkJbm9kZSA9IHBhcmVudFN0YWNrLnBlZWsoKTsKICAgICAgICAJCUludGVnZXIgaSA9IGNoaWxkSW5kZXhTdGFjay5wb3AoKSArIDE7CiAgICAgICAgCQlpZiAoaSA+PSBub2RlLmNoaWxkcmVuLnNpemUoKSkgewogICAgICAgIAkJCW5vZGUgPSBudWxsOwogICAgICAgIAkJCXBhcmVudFN0YWNrLnBvcCgpOwogICAgICAgIAkJfSBlbHNlIHsKICAgICAgICAJCQlub2RlID0gbm9kZS5jaGlsZHJlbi5nZXQoaSk7CiAgICAgICAgCQkJY2hpbGRJbmRleFN0YWNrLnB1c2goaSk7CiAgICAgICAgCQl9CgkgICAgICAgICAgICAKCSAgICAgICAgfQogICAgICAgIAogICAgICAgIH0KICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAKCX0KCgp9