Skip to content

Instantly share code, notes, and snippets.

@tynes
Created October 26, 2016 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tynes/6a8b73254f7b3343b3d0d025f44e6d2b to your computer and use it in GitHub Desktop.
Save tynes/6a8b73254f7b3343b3d0d025f44e6d2b to your computer and use it in GitHub Desktop.
binary tree traversal to find common ancestor
const BinaryTree = class {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
addLeftChild(value) {
if (this.left) {
console.log('Left child being overwritten');
}
this.left = new BinaryTree(value);
}
addRightChild(value) {
if (this.right) {
console.log('Right child being overwritten');
}
this.right = new BinaryTree(value);
}
}
const jack = new BinaryTree('Jack');
const tom = jack.left = new BinaryTree('Tom');
const matt = jack.right = new BinaryTree('Matt');
const fred = tom.left = new BinaryTree('Fred');
const lorin = fred.right = new BinaryTree('Lorin');
const benny = matt.right = new BinaryTree('Benny');
const yheti = matt.left = new BinaryTree('Yheti');
/*
Tree structure
jack
/ \
tom matt
/ / \
fred yheti benny
/
lorin
*/
const commonAncestor = (rootNode, memberA, memberB) => {
// object of arrays, key is member name
// value is array of lineage members, index 0 is root
const ancestry = {};
const traverse = (node, lineage = []) => {
lineage.push(node.value);
ancestry[node.value] = [...lineage];
if (node.left) {
traverse(node.left, lineage);
lineage.pop();
}
if (node.right) {
traverse(node.right, lineage);
lineage.pop();
}
}
// generate the lineages inside of the ancestry object
traverse(rootNode);
const memberALineage = ancestry[memberA.value];
const memberBLineage = ancestry[memberB.value];
// one array may be longer than the other
const length = Math.max(memberALineage.length, memberBLineage.length);
// iterate through lineages and find the divergence
for (let i = 0; i < length; i++) {
let hasLineageDiverged = memberALineage[i] !== memberBLineage[i];
// double check is previous element the same
let isPreviousSame = memberALineage[i - 1] === memberBLineage[i - 1];
if (hasLineageDiverged && isPreviousSame) {
return memberALineage[i - 1];
}
}
return null;
};
// matt is the first common ancestor
const result = commonAncestor(jack, benny, yheti);
console.log(result); // Matt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment