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