Skip to content

Commit 0dddf20

Browse files
committed
Lowest coomon ancestor of a binary search tree
1 parent 9942848 commit 0dddf20

File tree

2 files changed

+263
-0
lines changed

2 files changed

+263
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// 235. Lowest coomon ancestor of a binary search tree
2+
// Topics: 'Depth-First Search', 'Tree', 'Binary Search Tree', 'Binary Tree'
3+
// Level: 'Medium'
4+
5+
// Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST.
6+
7+
// According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
8+
9+
// Example 1:
10+
11+
// Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
12+
// Output: 6
13+
// Explanation: The LCA of nodes 2 and 8 is 6.
14+
15+
// Example 2:
16+
17+
// Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
18+
// Output: 2
19+
// Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
20+
21+
// Example 3:
22+
23+
// Input: root = [2,1], p = 2, q = 1
24+
// Output: 2
25+
26+
// Constraints:
27+
28+
// The number of nodes in the tree is in the range [2, 105].
29+
// -109 <= Node.val <= 109
30+
// All Node.val are unique.
31+
// p != q
32+
// p and q will exist in the BST.
33+
34+
package lowestcommonancestorofabinarysearchtree
35+
36+
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
37+
if p.Val < root.Val && q.Val < root.Val {
38+
return lowestCommonAncestor(root.Left, p, q)
39+
}
40+
if p.Val > root.Val && q.Val > root.Val {
41+
return lowestCommonAncestor(root.Right, p, q)
42+
}
43+
return root
44+
}
45+
46+
type TreeNode struct {
47+
Right *TreeNode
48+
Left *TreeNode
49+
Val int
50+
}
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package lowestcommonancestorofabinarysearchtree
2+
3+
import "testing"
4+
5+
func TestLowestCommonAncestor(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
root *TreeNode
9+
p *TreeNode
10+
q *TreeNode
11+
expected int
12+
}{
13+
{
14+
name: "Example 1: LCA of 2 and 8 is 6",
15+
// 6
16+
// / \
17+
// 2 8
18+
// / \ / \
19+
// 0 4 7 9
20+
// / \
21+
// 3 5
22+
root: &TreeNode{
23+
Val: 6,
24+
Left: &TreeNode{
25+
Val: 2,
26+
Left: &TreeNode{
27+
Val: 0,
28+
},
29+
Right: &TreeNode{
30+
Val: 4,
31+
Left: &TreeNode{
32+
Val: 3,
33+
},
34+
Right: &TreeNode{
35+
Val: 5,
36+
},
37+
},
38+
},
39+
Right: &TreeNode{
40+
Val: 8,
41+
Left: &TreeNode{
42+
Val: 7,
43+
},
44+
Right: &TreeNode{
45+
Val: 9,
46+
},
47+
},
48+
},
49+
p: &TreeNode{Val: 2},
50+
q: &TreeNode{Val: 8},
51+
expected: 6,
52+
},
53+
{
54+
name: "Example 2: LCA of 2 and 4 is 2",
55+
// 6
56+
// / \
57+
// 2 8
58+
// / \ / \
59+
// 0 4 7 9
60+
// / \
61+
// 3 5
62+
root: &TreeNode{
63+
Val: 6,
64+
Left: &TreeNode{
65+
Val: 2,
66+
Left: &TreeNode{
67+
Val: 0,
68+
},
69+
Right: &TreeNode{
70+
Val: 4,
71+
Left: &TreeNode{
72+
Val: 3,
73+
},
74+
Right: &TreeNode{
75+
Val: 5,
76+
},
77+
},
78+
},
79+
Right: &TreeNode{
80+
Val: 8,
81+
Left: &TreeNode{
82+
Val: 7,
83+
},
84+
Right: &TreeNode{
85+
Val: 9,
86+
},
87+
},
88+
},
89+
p: &TreeNode{Val: 2},
90+
q: &TreeNode{Val: 4},
91+
expected: 2,
92+
},
93+
{
94+
name: "Example 3: LCA of 2 and 1 is 2",
95+
// 2
96+
// /
97+
// 1
98+
root: &TreeNode{
99+
Val: 2,
100+
Left: &TreeNode{
101+
Val: 1,
102+
},
103+
},
104+
p: &TreeNode{Val: 2},
105+
q: &TreeNode{Val: 1},
106+
expected: 2,
107+
},
108+
{
109+
name: "LCA of 0 and 5 is 2",
110+
// 6
111+
// / \
112+
// 2 8
113+
// / \ / \
114+
// 0 4 7 9
115+
// / \
116+
// 3 5
117+
root: &TreeNode{
118+
Val: 6,
119+
Left: &TreeNode{
120+
Val: 2,
121+
Left: &TreeNode{
122+
Val: 0,
123+
},
124+
Right: &TreeNode{
125+
Val: 4,
126+
Left: &TreeNode{
127+
Val: 3,
128+
},
129+
Right: &TreeNode{
130+
Val: 5,
131+
},
132+
},
133+
},
134+
Right: &TreeNode{
135+
Val: 8,
136+
Left: &TreeNode{
137+
Val: 7,
138+
},
139+
Right: &TreeNode{
140+
Val: 9,
141+
},
142+
},
143+
},
144+
p: &TreeNode{Val: 0},
145+
q: &TreeNode{Val: 5},
146+
expected: 2,
147+
},
148+
{
149+
name: "LCA of 7 and 9 is 8",
150+
// 6
151+
// / \
152+
// 2 8
153+
// / \ / \
154+
// 0 4 7 9
155+
// / \
156+
// 3 5
157+
root: &TreeNode{
158+
Val: 6,
159+
Left: &TreeNode{
160+
Val: 2,
161+
Left: &TreeNode{
162+
Val: 0,
163+
},
164+
Right: &TreeNode{
165+
Val: 4,
166+
Left: &TreeNode{
167+
Val: 3,
168+
},
169+
Right: &TreeNode{
170+
Val: 5,
171+
},
172+
},
173+
},
174+
Right: &TreeNode{
175+
Val: 8,
176+
Left: &TreeNode{
177+
Val: 7,
178+
},
179+
Right: &TreeNode{
180+
Val: 9,
181+
},
182+
},
183+
},
184+
p: &TreeNode{Val: 7},
185+
q: &TreeNode{Val: 9},
186+
expected: 8,
187+
},
188+
{
189+
name: "Small tree with two nodes",
190+
// 10
191+
// /
192+
// 5
193+
root: &TreeNode{
194+
Val: 10,
195+
Left: &TreeNode{
196+
Val: 5,
197+
},
198+
},
199+
p: &TreeNode{Val: 10},
200+
q: &TreeNode{Val: 5},
201+
expected: 10,
202+
},
203+
}
204+
205+
for _, tt := range tests {
206+
t.Run(tt.name, func(t *testing.T) {
207+
result := lowestCommonAncestor(tt.root, tt.p, tt.q)
208+
if result.Val != tt.expected {
209+
t.Errorf("expected %d, got %d", tt.expected, result.Val)
210+
}
211+
})
212+
}
213+
}

0 commit comments

Comments
 (0)