1+ package com .ctci .treesandgraphs ;
2+
3+ /**
4+ * Design an algorithm and write code to find the first common ancestor of two nodes in a binary
5+ * tree. Avoid storing additional nodes in a data structure. Also, for this question, the tree node
6+ * has access to its parent node. NOTE: This is not necessarily a binary search tree.
7+ *
8+ * @author rampatra
9+ * @since 2019-02-23
10+ */
11+ public class LeastCommonAncestorWithParentAccess {
12+
13+ /**
14+ * This is a simple approach where we start with two references, one pointing to {@code node a} and another
15+ * pointing to {@code node b}. We move the reference pointing to the deeper node upwards, if required, so that
16+ * both the references are at the same depth from root. After both the references are at same depth, we simply
17+ * move both the references upwards until they merge. The node at which they merge is our LCA.
18+ *
19+ * @param a
20+ * @param b
21+ * @return the least common ancestor node
22+ */
23+ private static TreeNode findLCA (TreeNode a , TreeNode b ) {
24+ if (a == null || b == null ) {
25+ return null ;
26+ }
27+
28+ int depthA = depth (a );
29+ int depthB = depth (b );
30+ // be little careful when both nodes are at same depth
31+ TreeNode shallowNode = depthA < depthB ? a : b ;
32+ TreeNode deeperNode = depthB > depthA ? b : a ;
33+
34+ // move deeper node reference upwards so that both the references are at same depth
35+ deeperNode = goUpBy (deeperNode , Math .abs (depthA - depthB ));
36+
37+ while (shallowNode != deeperNode && shallowNode != null && deeperNode != null ) {
38+ shallowNode = shallowNode .parent ;
39+ deeperNode = deeperNode .parent ;
40+ }
41+
42+ return shallowNode ;
43+ }
44+
45+ private static int depth (TreeNode node ) {
46+ int d = 0 ;
47+ while (node != null && node .parent != null ) {
48+ d ++;
49+ node = node .parent ;
50+ }
51+ return d ;
52+ }
53+
54+ private static TreeNode goUpBy (TreeNode node , int levelsUp ) {
55+ int c = 0 ;
56+ while (node != null && c < levelsUp ) {
57+ node = node .parent ;
58+ c ++;
59+ }
60+ return node ;
61+ }
62+
63+ private static class TreeNode {
64+ int val ;
65+ TreeNode parent ;
66+ TreeNode left ;
67+ TreeNode right ;
68+
69+ TreeNode (int val ) {
70+ this .val = val ;
71+ }
72+ }
73+
74+ public static void main (String [] args ) {
75+ /*
76+ The binary tree looks like:
77+
78+ 4
79+ / \
80+ 5 8
81+ / \ / \
82+ 1 3 2 9
83+ / \
84+ 0 7
85+
86+ */
87+ TreeNode treeRoot = new TreeNode (4 );
88+ treeRoot .left = new TreeNode (5 );
89+ treeRoot .left .parent = treeRoot ;
90+ treeRoot .right = new TreeNode (8 );
91+ treeRoot .right .parent = treeRoot ;
92+ treeRoot .left .left = new TreeNode (1 );
93+ treeRoot .left .left .parent = treeRoot .left ;
94+ treeRoot .left .right = new TreeNode (3 );
95+ treeRoot .left .right .parent = treeRoot .left ;
96+ treeRoot .left .left .left = new TreeNode (0 );
97+ treeRoot .left .left .left .parent = treeRoot .left .left ;
98+ treeRoot .right .left = new TreeNode (2 );
99+ treeRoot .right .left .parent = treeRoot .right ;
100+ treeRoot .right .right = new TreeNode (9 );
101+ treeRoot .right .right .parent = treeRoot .right ;
102+ treeRoot .right .left .right = new TreeNode (7 );
103+ treeRoot .right .left .right .parent = treeRoot .right .left ;
104+
105+ System .out .println ("LCA of 0 and 7 is: " + findLCA (treeRoot .left .left .left , treeRoot .right .left .right ).val );
106+ System .out .println ("LCA of 0 and 9 is: " + findLCA (treeRoot .left .left .left , treeRoot .right .right ).val );
107+ System .out .println ("LCA of 0 and 1 is: " + findLCA (treeRoot .left .left .left , treeRoot .left .left ).val );
108+ System .out .println ("LCA of 1 and 2 is: " + findLCA (treeRoot .left .left , treeRoot .right .left ).val );
109+ System .out .println ("LCA of 1 and 7 is: " + findLCA (treeRoot .left .left , treeRoot .right .left .right ).val );
110+ System .out .println ("LCA of 4 and 7 is: " + findLCA (treeRoot , treeRoot .right .left .right ).val );
111+ System .out .println ("LCA of 5 and 2 is: " + findLCA (treeRoot .left , treeRoot .right .left ).val );
112+ System .out .println ("LCA of 7 and 9 is: " + findLCA (treeRoot .right .left .right , treeRoot .right .right ).val );
113+ }
114+ }
0 commit comments