@@ -24,7 +24,22 @@ def swap(a: int, b: int) -> tuple[int, int]:
24
24
25
25
def create_sparse (max_node : int , parent : list [list [int ]]) -> list [list [int ]]:
26
26
"""
27
- creating sparse table which saves each nodes 2^i-th parent
27
+ Create a sparse table which saves each node's 2^i-th parent.
28
+
29
+ >>> max_node = 5
30
+ >>> parent = [
31
+ ... [0, 0, 1, 1, 2, 2], # 2^0-th parents
32
+ ... [0, 0, 0, 0, 1, 1] # 2^1-th parents
33
+ ... ]
34
+ >>> create_sparse(max_node, parent)
35
+ [[0, 0, 1, 1, 2, 2], [0, 0, 0, 0, 1, 1]]
36
+ >>> max_node = 3
37
+ >>> parent = [
38
+ ... [0, 0, 1, 1], # 2^0-th parents
39
+ ... [0, 0, 0, 0] # 2^1-th parents
40
+ ... ]
41
+ >>> create_sparse(max_node, parent)
42
+ [[0, 0, 1, 1], [0, 0, 0, 0]]
28
43
"""
29
44
j = 1
30
45
while (1 << j ) < max_node :
@@ -38,6 +53,46 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
38
53
def lowest_common_ancestor (
39
54
u : int , v : int , level : list [int ], parent : list [list [int ]]
40
55
) -> int :
56
+ """
57
+ Return the lowest common ancestor of nodes u and v.
58
+
59
+ >>> max_node = 13
60
+ >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
61
+ >>> level = [-1 for _ in range(max_node + 10)]
62
+ >>> graph = {
63
+ ... 1: [2, 3, 4],
64
+ ... 2: [5],
65
+ ... 3: [6, 7],
66
+ ... 4: [8],
67
+ ... 5: [9, 10],
68
+ ... 6: [11],
69
+ ... 7: [],
70
+ ... 8: [12, 13],
71
+ ... 9: [],
72
+ ... 10: [],
73
+ ... 11: [],
74
+ ... 12: [],
75
+ ... 13: [],
76
+ ... }
77
+ >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
78
+ >>> parent = create_sparse(max_node, parent)
79
+ >>> lowest_common_ancestor(1, 3, level, parent)
80
+ 1
81
+ >>> lowest_common_ancestor(5, 6, level, parent)
82
+ 1
83
+ >>> lowest_common_ancestor(7, 11, level, parent)
84
+ 1
85
+ >>> lowest_common_ancestor(6, 7, level, parent)
86
+ 3
87
+ >>> lowest_common_ancestor(4, 12, level, parent)
88
+ 4
89
+ >>> lowest_common_ancestor(8, 8, level, parent)
90
+ 8
91
+ >>> lowest_common_ancestor(9, 10, level, parent)
92
+ 5
93
+ >>> lowest_common_ancestor(12, 13, level, parent)
94
+ 8
95
+ """
41
96
# u must be deeper in the tree than v
42
97
if level [u ] < level [v ]:
43
98
u , v = swap (u , v )
@@ -65,9 +120,54 @@ def breadth_first_search(
65
120
root : int = 1 ,
66
121
) -> tuple [list [int ], list [list [int ]]]:
67
122
"""
68
- sets every nodes direct parent
69
- parent of root node is set to 0
70
- calculates depth of each node from root node
123
+ Perform a breadth-first search from the root node of the tree.
124
+ Sets every node's direct parent and calculates the depth of each node from the root.
125
+
126
+ >>> max_node = 5
127
+ >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
128
+ >>> level = [-1 for _ in range(max_node + 10)]
129
+ >>> graph = {
130
+ ... 1: [2, 3],
131
+ ... 2: [4],
132
+ ... 3: [5],
133
+ ... 4: [],
134
+ ... 5: []
135
+ ... }
136
+ >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
137
+ >>> level[:6]
138
+ [ -1, 0, 1, 1, 2, 2]
139
+ >>> parent[0][1] == 0
140
+ True
141
+ >>> parent[0][2] == 1
142
+ True
143
+ >>> parent[0][3] == 1
144
+ True
145
+ >>> parent[0][4] == 2
146
+ True
147
+ >>> parent[0][5] == 3
148
+ True
149
+
150
+ >>> # Test with disconnected graph
151
+ >>> max_node = 4
152
+ >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
153
+ >>> level = [-1 for _ in range(max_node + 10)]
154
+ >>> graph = {
155
+ ... 1: [2],
156
+ ... 2: [],
157
+ ... 3: [4],
158
+ ... 4: []
159
+ ... }
160
+ >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
161
+ >>> level[:5]
162
+ [ -1, 0, 1, -1, -1]
163
+ >>> parent[0][1] == 0
164
+ True
165
+ >>> parent[0][2] == 1
166
+ True
167
+ >>> parent[0][3] == 0
168
+ True
169
+ >>> parent[0][4] == 3
170
+ True
71
171
"""
72
172
level [root ] = 0
73
173
q : Queue [int ] = Queue (maxsize = max_node )
0 commit comments