Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: trekhleb/javascript-algorithms
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: 18-2-SKKU-OSS/javascript-algorithms
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: develop2
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 8 commits
  • 2 files changed
  • 1 contributor

Commits on Dec 5, 2018

  1. Copy the full SHA
    aba089c View commit details
  2. Copy the full SHA
    dbee69f View commit details
  3. Copy the full SHA
    5c6b4f2 View commit details
  4. Copy the full SHA
    643d6b2 View commit details
  5. update LCA algorithm

    orist22 committed Dec 5, 2018
    Copy the full SHA
    07602b9 View commit details
  6. update LCA algorithm

    orist22 committed Dec 5, 2018
    Copy the full SHA
    ee00302 View commit details
  7. update LCA algorithm

    orist22 committed Dec 5, 2018
    Copy the full SHA
    72f49d8 View commit details
  8. update LCA algorithms

    orist22 committed Dec 5, 2018
    Copy the full SHA
    17f3b8f View commit details
Showing with 68 additions and 0 deletions.
  1. +13 −0 src/algorithms/tree/lowest-common-ancestor/README.md
  2. +55 −0 src/algorithms/tree/lowest-common-ancestor/lowestCommonAncestor.js
13 changes: 13 additions & 0 deletions src/algorithms/tree/lowest-common-ancestor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Lowest common ancestor(LCA) algorithm

In graph theory and computer science, the lowest common ancestor (LCA) of two nodes v and w in a tree or directed acyclic graph (DAG) T is the lowest (i.e. deepest) node that has both v and w as descendants, where we define each node to be a descendant of itself (so if v has a direct connection from w, w is the lowest common ancestor).

The LCA of v and w in T is the shared ancestor of v and w that is located farthest from the root. Computation of lowest common ancestors may be useful, for instance, as part of a procedure for determining the distance between pairs of nodes in a tree: the distance from v to w can be computed as the distance from the root to v, plus the distance from the root to w, minus twice the distance from the root to their lowest common ancestor (Djidjev, Pantziou & Zaroliagis 1991). In ontologies, the lowest common ancestor is also known as the least common subsumer.

In a tree data structure where each node points to its parent, the lowest common ancestor can be easily determined by finding the first intersection of the paths from v and w to the root. In general, the computational time required for this algorithm is O(h) where h is the height of the tree (length of longest path from a leaf to the root). However, there exist several algorithms for processing trees so that lowest common ancestors may be found more quickly. Tarjan's off-line lowest common ancestors algorithm, for example, preprocesses a tree in linear time to provide constant-time LCA queries. In general DAGs, similar algorithms exist, but with super-linear complexity.


## References

- [Wikipedia](https://en.wikipedia.org/wiki/Lowest_common_ancestor) (https://en.wikipedia.org/wiki/Lowest_common_ancestor)

55 changes: 55 additions & 0 deletions src/algorithms/tree/lowest-common-ancestor/lowestCommonAncestor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @typedef {Object} Callbacks
* @property {function(node: BinaryTreeNode, child: BinaryTreeNode): boolean} allowTraversal -
* Determines whether DFS should traverse from the node to its child.
*/

/**
* @param {Callbacks} [callbacks]
* @returns {Callbacks}
*/

/**
* @param {BinaryTreeNode} rootNode
* @param {Callbacks} [originalCallbacks]
*/
function calcDepth(node) {
let depth = 0;
let tempNode = null;
tempNode = node;
while (tempNode.parent == null) {
tempNode = tempNode.parent;
depth += 1;
}

return depth;
}

/* lowest common ancestor */
export default function lca(rootNode, firstNode, secondNode) {
const firstDepth = calcDepth(firstNode);
const secondDepth = calcDepth(secondNode);
let firstOne = null;
let secondOne = null;
firstOne = firstNode;
secondOne = secondNode;

for (let i = 0; i < Math.abs(firstDepth - secondDepth); i += 1) {
if (firstDepth > secondDepth) {
firstOne = firstOne.parent;
} else {
secondOne = secondOne.parent;
}
}

if (firstNode === secondNode) {
return firstOne;
}

while (firstOne !== secondOne) {
firstOne = firstOne.parent;
secondOne = secondOne.parent;
}

return firstOne;
}