Lowest Common Ancestor of Binary Tree(Not Binary Search Tree)

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

I tried working out the problem using Tarjan's Algorithm and one algorithm from the website: http://discuss.techinterview.org/default.asp?interview.11.532716.6, but none is clear. Maybe my recursion concepts are not build up properly. Please give small demonstration to explain the above two examples. I have an idea of Union Find data-structure.

It looks very interesting problem. So have to decode the problem anyhow. Preparing for the interviews.

If any other logic/algorithm exist, please share.

回答1:

The LCA algorithm tries to do a simple thing: Figure out paths from the two nodes in question to the root. Now, these two paths would have a common suffix (assuming that the path ends at the root). The LCA is the first node where the suffix begins.

Consider the following tree:

              r *                 / \             s *   *              / \           u *   * t            /   / \           * v *   *              / \             *   *

In order to find the LCA(u, v) we proceed as follows:

  • Path from u to root: Path(u, r) = usr
  • Path from v to root: Path(v, r) = vtsr

Now, we check for the common suffix:

  • Common suffix: 'sr'
  • Therefore LCA(u, v) = first node of the suffix = s

Note the actual algorithms do not go all the way up to the root. They use Disjoint-Set data structures to stop when they reach s.

An excellent set of alternative approaches are explained here.



回答2:

Since you mentioned job interviews, I thought of the variation of this problem where you are limited to O(1) memory usage.

In this case, consider the following algorithm:

1) Scan the tree from node u up to the root, finding the path length L(u)

2) Scan the tree from node v up to the root, finding the path length L(v)

3) Calculate the path length difference D = |L(u)-L(v)|

4) Skip D nodes in the longer path from the root

5) Walk up the tree in parallel from the two nodes, until you hit the same node

6) Return this node as the LCA



回答3:

Assuming you only need to solve the problem once (per data set) then a simple approach is to collect the set of ancestors from one node (along with itself), and then walk the list of ancestors from the other until you find a member of the above set, which is necessarily the lowest common ancestor. Pseudocode for that is given:

Let A and B begin as the nodes in question. seen := set containing the root node while A is not root:     add A to seen     A := A's parent while B is not in seen:     B := B's parent B is now the lowest common ancestor.

Another method is to compute the entire path-to-room for each node, then scan from the right looking for a common suffix. Its first element is the LCA. Which one of these is faster depends on your data.

If you will be needing to find LCAs of many pairs of nodes, then you can make various space/time trade-offs:

You could, for instance, pre-compute the depth of each node, which would allow you to avoid re-creating the sets(or paths) each time by first walking from the deeper node to the depth of the shallower node, and then walking the two nodes toward the root in lock step: when these paths meet, you have the LCA.

Another approach annotates nodes with their next ancestor at depth-mod-H, so that you first solve a similar-but-H-times-smaller problem and then an H-sized instance of the first problem. This is good on very deep trees, and H is generally chosen as the square root of the average depth of the tree.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!