Skip to content

Commit 68cd62c

Browse files
modified
1 parent 419cccc commit 68cd62c

File tree

1 file changed

+18
-29
lines changed

1 file changed

+18
-29
lines changed

data_structures/binary_tree/lowest_common_ancestor.py

+18-29
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
# https://en.wikipedia.org/wiki/Lowest_common_ancestor
2+
# https://en.wikipedia.org/wiki/Breadth-first_search
3+
14
from __future__ import annotations
5+
26
from queue import Queue
37

48

59
def swap(a: int, b: int) -> tuple[int, int]:
610
"""
7-
Return a tuple (b, a) when given two integers a and b.
8-
9-
>>> swap(2, 3)
11+
Return a tuple (b, a) when given two integers a and b
12+
>>> swap(2,3)
1013
(3, 2)
11-
>>> swap(3, 4)
14+
>>> swap(3,4)
1215
(4, 3)
1316
>>> swap(67, 12)
1417
(12, 67)
@@ -33,7 +36,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
3336
For example, consider a small tree where:
3437
- Node 1 is the root (its parent is 0),
3538
- Nodes 2 and 3 have parent 1.
36-
39+
3740
We set up the parent table for only two levels (row 0 and row 1)
3841
for max_node = 3. (Note that in practice the table has many rows.)
3942
@@ -52,23 +55,17 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
5255
return parent
5356

5457

58+
# returns lca of node u,v
5559
def lowest_common_ancestor(
5660
u: int, v: int, level: list[int], parent: list[list[int]]
5761
) -> int:
5862
"""
5963
Return the lowest common ancestor (LCA) of nodes u and v in a tree.
60-
<<<<<<< HEAD
6164
6265
The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
6366
of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
6467
of node i.
6568
66-
=======
67-
68-
The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
69-
and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
70-
71-
>>>>>>> 097e9c6149e80f095be1b3dbef1c04ff94a7325a
7269
>>> # Consider a simple tree:
7370
>>> # 1
7471
>>> # / \\
@@ -81,23 +78,25 @@ def lowest_common_ancestor(
8178
>>> lowest_common_ancestor(2, 2, level, parent)
8279
2
8380
"""
84-
# Ensure u is at least as deep as v.
81+
# u must be deeper in the tree than v
8582
if level[u] < level[v]:
8683
u, v = swap(u, v)
87-
# Bring u up to the same level as v.
84+
# making depth of u same as depth of v
8885
for i in range(18, -1, -1):
8986
if level[u] - (1 << i) >= level[v]:
9087
u = parent[i][u]
91-
# If they are the same, we've found the LCA.
88+
# at the same depth if u==v that mean lca is found
9289
if u == v:
9390
return u
94-
# Move u and v up together until the LCA is found.
91+
# moving both nodes upwards till lca in found
9592
for i in range(18, -1, -1):
9693
if parent[i][u] not in [0, parent[i][v]]:
9794
u, v = parent[i][u], parent[i][v]
95+
# returning longest common ancestor of u,v
9896
return parent[0][u]
9997

10098

99+
# runs a breadth first search from root node of the tree
101100
def breadth_first_search(
102101
level: list[int],
103102
parent: list[list[int]],
@@ -143,7 +142,6 @@ def main() -> None:
143142
sparse table and compute several lowest common ancestors.
144143
145144
The sample tree used is:
146-
<<<<<<< HEAD
147145
148146
1
149147
/ | \
@@ -153,17 +151,6 @@ def main() -> None:
153151
/ \\ | / \\
154152
9 10 11 12 13
155153
156-
=======
157-
158-
1
159-
/ | \
160-
2 3 4
161-
/ / \\ \\
162-
5 6 7 8
163-
/ \\ | / \\
164-
9 10 11 12 13
165-
166-
>>>>>>> 097e9c6149e80f095be1b3dbef1c04ff94a7325a
167154
The expected lowest common ancestors are:
168155
- LCA(1, 3) --> 1
169156
- LCA(5, 6) --> 1
@@ -173,7 +160,7 @@ def main() -> None:
173160
- LCA(8, 8) --> 8
174161
175162
To test main() without it printing to the console, we capture the output.
176-
163+
177164
>>> import sys
178165
>>> from io import StringIO
179166
>>> backup = sys.stdout
@@ -187,7 +174,9 @@ def main() -> None:
187174
True
188175
"""
189176
max_node = 13
177+
# initializing with 0
190178
parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
179+
# initializing with -1 which means every node is unvisited
191180
level = [-1 for _ in range(max_node + 10)]
192181
graph: dict[int, list[int]] = {
193182
1: [2, 3, 4],

0 commit comments

Comments
 (0)