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