Skip to content

Commit d6fff75

Browse files
Modified doctest
1 parent b74d7f5 commit d6fff75

File tree

1 file changed

+32
-40
lines changed

1 file changed

+32
-40
lines changed

data_structures/binary_tree/lowest_common_ancestor.py

+32-40
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# https://en.wikipedia.org/wiki/Lowest_common_ancestor
2-
# https://en.wikipedia.org/wiki/Breadth-first_search
3-
41
from __future__ import annotations
52
from queue import Queue
63

@@ -25,29 +22,27 @@ def swap(a: int, b: int) -> tuple[int, int]:
2522
def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
2623
"""
2724
Create a sparse table that saves each node's 2^i-th parent.
28-
29-
The given `parent` table should have the direct parent of each node in row 0.
30-
The function then fills in parent[j][i] = parent[j-1][parent[j-1][i]] for each j where 2^j < max_node.
31-
25+
26+
The given ``parent`` table should have the direct parent of each node in row 0.
27+
This function fills in:
28+
29+
parent[j][i] = parent[j - 1][parent[j - 1][i]]
30+
31+
for each j where 2^j is less than max_node.
32+
3233
For example, consider a small tree where:
3334
- Node 1 is the root (its parent is 0),
3435
- Nodes 2 and 3 have parent 1.
3536
3637
We set up the parent table for only two levels (row 0 and row 1)
3738
for max_node = 3. (Note that in practice the table has many rows.)
38-
39-
>>> # Create an initial parent table with 2 rows and indices 0..3.
40-
>>> parent0 = [0, 0, 1, 1] # 0 is unused; node1's parent=0, node2 and 3's parent=1.
39+
40+
>>> parent0 = [0, 0, 1, 1] # 0 is unused; node1's parent=0, nodes 2 and 3's parent=1.
4141
>>> parent1 = [0, 0, 0, 0]
4242
>>> parent = [parent0, parent1]
43-
>>> # We need at least (1 << j) < max_node holds only for j = 1 here since (1 << 1)=2 < 3 and (1 << 2)=4 !< 3.
4443
>>> sparse = create_sparse(3, parent)
45-
>>> sparse[1][1], sparse[1][2], sparse[1][3]
44+
>>> (sparse[1][1], sparse[1][2], sparse[1][3])
4645
(0, 0, 0)
47-
>>> # Explanation:
48-
>>> # For node 1: parent[1][1] = parent[0][parent[0][1]] = parent[0][0] = 0.
49-
>>> # For node 2: parent[1][2] = parent[0][parent[0][2]] = parent[0][1] = 0.
50-
>>> # For node 3: parent[1][3] = parent[0][parent[0][3]] = parent[0][1] = 0.
5146
"""
5247
j = 1
5348
while (1 << j) < max_node:
@@ -62,20 +57,20 @@ def lowest_common_ancestor(
6257
) -> int:
6358
"""
6459
Return the lowest common ancestor (LCA) of nodes u and v in a tree.
65-
66-
The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
67-
and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
60+
61+
The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
62+
of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
63+
of node i.
6864
6965
>>> # Consider a simple tree:
7066
>>> # 1
7167
>>> # / \\
7268
>>> # 2 3
73-
>>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0,0,1,1]
69+
>>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0, 0, 1, 1]
7470
>>> level = [-1, 0, 1, 1] # index 0 is dummy
7571
>>> parent = [[0, 0, 1, 1]] + [[0, 0, 0, 0] for _ in range(19)]
7672
>>> lowest_common_ancestor(2, 3, level, parent)
7773
1
78-
>>> # LCA of a node with itself is itself.
7974
>>> lowest_common_ancestor(2, 2, level, parent)
8075
2
8176
"""
@@ -93,7 +88,6 @@ def lowest_common_ancestor(
9388
for i in range(18, -1, -1):
9489
if parent[i][u] not in [0, parent[i][v]]:
9590
u, v = parent[i][u], parent[i][v]
96-
# Return the parent (direct ancestor) which is the LCA.
9791
return parent[0][u]
9892

9993

@@ -106,10 +100,10 @@ def breadth_first_search(
106100
) -> tuple[list[int], list[list[int]]]:
107101
"""
108102
Run a breadth-first search (BFS) from the root node of the tree.
109-
110-
Sets every node's direct parent (in parent[0]) and calculates the depth (level)
111-
of each node from the root.
112-
103+
104+
This sets each node's direct parent (stored in parent[0]) and calculates the
105+
depth (level) of each node from the root.
106+
113107
>>> # Consider a simple tree:
114108
>>> # 1
115109
>>> # / \\
@@ -138,27 +132,27 @@ def breadth_first_search(
138132

139133
def main() -> None:
140134
"""
141-
Run a BFS to set node depths and parents in a sample tree,
142-
then create the sparse table and compute several lowest common ancestors.
143-
135+
Run a BFS to set node depths and parents in a sample tree, then create the
136+
sparse table and compute several lowest common ancestors.
137+
144138
The sample tree used is:
145139
146-
1
147-
/ | \
148-
2 3 4
149-
/ / \\ \\
150-
5 6 7 8
151-
/ \\ | / \\
152-
9 10 11 12 13
153-
140+
1
141+
/ | \
142+
2 3 4
143+
/ / \\ \\
144+
5 6 7 8
145+
/ \\ | / \\
146+
9 10 11 12 13
147+
154148
The expected lowest common ancestors are:
155149
- LCA(1, 3) --> 1
156150
- LCA(5, 6) --> 1
157151
- LCA(7, 11) --> 3
158152
- LCA(6, 7) --> 3
159153
- LCA(4, 12) --> 4
160154
- LCA(8, 8) --> 8
161-
155+
162156
To test main() without it printing to the console, we capture the output.
163157
164158
>>> import sys
@@ -174,9 +168,7 @@ def main() -> None:
174168
True
175169
"""
176170
max_node = 13
177-
# initializing with 0; extra space is allocated.
178171
parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
179-
# initializing with -1 which means every node is unvisited.
180172
level = [-1 for _ in range(max_node + 10)]
181173
graph: dict[int, list[int]] = {
182174
1: [2, 3, 4],

0 commit comments

Comments
 (0)