1
+ # https://en.wikipedia.org/wiki/Lowest_common_ancestor
2
+ # https://en.wikipedia.org/wiki/Breadth-first_search
3
+
1
4
from __future__ import annotations
5
+
2
6
from queue import Queue
3
7
4
8
5
9
def swap (a : int , b : int ) -> tuple [int , int ]:
6
10
"""
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)
10
13
(3, 2)
11
- >>> swap(3, 4)
14
+ >>> swap(3,4)
12
15
(4, 3)
13
16
>>> swap(67, 12)
14
17
(12, 67)
@@ -33,7 +36,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
33
36
For example, consider a small tree where:
34
37
- Node 1 is the root (its parent is 0),
35
38
- Nodes 2 and 3 have parent 1.
36
-
39
+
37
40
We set up the parent table for only two levels (row 0 and row 1)
38
41
for max_node = 3. (Note that in practice the table has many rows.)
39
42
@@ -52,23 +55,17 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
52
55
return parent
53
56
54
57
58
+ # returns lca of node u,v
55
59
def lowest_common_ancestor (
56
60
u : int , v : int , level : list [int ], parent : list [list [int ]]
57
61
) -> int :
58
62
"""
59
63
Return the lowest common ancestor (LCA) of nodes u and v in a tree.
60
- <<<<<<< HEAD
61
64
62
65
The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
63
66
of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
64
67
of node i.
65
68
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
72
69
>>> # Consider a simple tree:
73
70
>>> # 1
74
71
>>> # / \\
@@ -81,23 +78,25 @@ def lowest_common_ancestor(
81
78
>>> lowest_common_ancestor(2, 2, level, parent)
82
79
2
83
80
"""
84
- # Ensure u is at least as deep as v.
81
+ # u must be deeper in the tree than v
85
82
if level [u ] < level [v ]:
86
83
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
88
85
for i in range (18 , - 1 , - 1 ):
89
86
if level [u ] - (1 << i ) >= level [v ]:
90
87
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
92
89
if u == v :
93
90
return u
94
- # Move u and v up together until the LCA is found.
91
+ # moving both nodes upwards till lca in found
95
92
for i in range (18 , - 1 , - 1 ):
96
93
if parent [i ][u ] not in [0 , parent [i ][v ]]:
97
94
u , v = parent [i ][u ], parent [i ][v ]
95
+ # returning longest common ancestor of u,v
98
96
return parent [0 ][u ]
99
97
100
98
99
+ # runs a breadth first search from root node of the tree
101
100
def breadth_first_search (
102
101
level : list [int ],
103
102
parent : list [list [int ]],
@@ -143,7 +142,6 @@ def main() -> None:
143
142
sparse table and compute several lowest common ancestors.
144
143
145
144
The sample tree used is:
146
- <<<<<<< HEAD
147
145
148
146
1
149
147
/ | \
@@ -153,17 +151,6 @@ def main() -> None:
153
151
/ \\ | / \\
154
152
9 10 11 12 13
155
153
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
167
154
The expected lowest common ancestors are:
168
155
- LCA(1, 3) --> 1
169
156
- LCA(5, 6) --> 1
@@ -173,7 +160,7 @@ def main() -> None:
173
160
- LCA(8, 8) --> 8
174
161
175
162
To test main() without it printing to the console, we capture the output.
176
-
163
+
177
164
>>> import sys
178
165
>>> from io import StringIO
179
166
>>> backup = sys.stdout
@@ -187,7 +174,9 @@ def main() -> None:
187
174
True
188
175
"""
189
176
max_node = 13
177
+ # initializing with 0
190
178
parent = [[0 for _ in range (max_node + 10 )] for _ in range (20 )]
179
+ # initializing with -1 which means every node is unvisited
191
180
level = [- 1 for _ in range (max_node + 10 )]
192
181
graph : dict [int , list [int ]] = {
193
182
1 : [2 , 3 , 4 ],
0 commit comments