However spoiler alert: the results are quite disappointing.
Getting to our quite deserved meat, here is the idea; if we have a tree with parent pointers, we can use them to walk the distance between two elements as follows:
- navigate from the root to the first element and keep track of its node and the travelled distance
- if the element is not there, we just return -1, otherwise we repeat the same operations for the second element
- if it is not there, again return -1, otherwise starting from the deepest (longest path) element, we navigate up the tree reducing the total path length for that element
- we check if the two nodes are equal, or if they share the same parent, or if we are the root. If not, we repeat the last step but this time maybe the deepest element is the other one so we will alternate
- keep doing this until the above condition is satisfied; that means we are at the lowest common ancestor and then the total distance is the sum of the remaining paths from this point to the two elements
- finding both elements is O(n) as usual
- navigating up from both elements is ... still O(n). Since we are navigating up and stopping at the root or a match, worst case is our ugly single branch tree and one element is the leaf and the other one is in the middle of the branch. We will navigate the tree halfway up before stopping, but that's still order n because sometimes the big O giveth and other times it taketh away :(
What is interesting though is that if the tree is balanced perfectly (log n height) we have of course better performance but just because of that since the overall result would not change between the three approaches!
You can check the code and a sample JUnit test source on my Gist. The full project was developed with IntelliJ and Gradle using JDK 8.
No comments:
Post a Comment
With great power comes great responsibility