From c85a338c0e48bb5547e0bbe93a5c6f2d03ad5b84 Mon Sep 17 00:00:00 2001 From: NidhaNureen Date: Mon, 14 Apr 2025 19:12:23 +1200 Subject: [PATCH 1/8] added doctests to functions in lowest_common_ancestor.py --- .../binary_tree/lowest_common_ancestor.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 651037703b95..9b59389456b7 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -25,6 +25,16 @@ def swap(a: int, b: int) -> tuple[int, int]: def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: """ creating sparse table which saves each nodes 2^i-th parent + >>> max_node = 6 + >>> parent = [[0, 0, 1, 1, 2, 2, 3]] + [[0] * 7 for _ in range(19)] + >>> parent = create_sparse(max_node, parent) + >>> parent[0] + [0, 0, 1, 1, 2, 2, 3] + >>> parent[1] + [0, 0, 0, 0, 1, 1, 1] + >>> parent[2] + [0, 0, 0, 0, 0, 0, 0] + """ j = 1 while (1 << j) < max_node: @@ -38,6 +48,26 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: def lowest_common_ancestor( u: int, v: int, level: list[int], parent: list[list[int]] ) -> int: + """ + Return the lowest common ancestor between u and v + + >>> level = [-1, 0, 1, 1, 2, 2, 2] + >>> parent = [[0, 0, 1, 1, 2, 2, 3],[0, 0, 0, 0, 1, 1, 1]] + [[0] * 7 for _ in range(17)] + >>> lowest_common_ancestor(4, 5, level, parent) + 2 + >>> lowest_common_ancestor(3, 6, level, parent) + 3 + >>> lowest_common_ancestor(4, 6, level, parent) + 1 + >>> lowest_common_ancestor(5, 6, level, parent) + 1 + >>> lowest_common_ancestor(2, 3, level, parent) + 1 + >>> lowest_common_ancestor(6, 6, level, parent) + 6 + >>> lowest_common_ancestor(1, 3, level, parent) + 1 + """ # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -56,6 +86,8 @@ def lowest_common_ancestor( return parent[0][u] + + # runs a breadth first search from root node of the tree def breadth_first_search( level: list[int], @@ -68,6 +100,30 @@ def breadth_first_search( sets every nodes direct parent parent of root node is set to 0 calculates depth of each node from root node + >>> level = [-1] * 7 + >>> parent = [[0] * 7 for _ in range(20)] + >>> graph = {1: [2, 3], 2: [4, 5], 3: [6], 4: [], 5: [], 6: []} + >>> level, parent = breadth_first_search(level, parent, 6, graph, 1) + >>> level + [-1, 0, 1, 1, 2, 2, 2] + >>> parent[0] + [0, 0, 1, 1, 2, 2, 3] + >>> parent[1] + [0, 0, 0, 0, 0, 0, 0] + >>> parent[2] + [0, 0, 0, 0, 0, 0, 0] + + # Edge case: graph with one node + >>> level = [-1] * 2 + >>> parent = [[0] * 2 for _ in range(20)] + >>> graph = {1: []} + >>> level, parent = breadth_first_search(level, parent, 1, graph, 1) + >>> level + [-1, 0] + >>> parent[0] + [0, 0] + >>> parent[1] + [0, 0] """ level[root] = 0 q: Queue[int] = Queue(maxsize=max_node) From f997aa0fb7ec42269750fa6e6b334cfeb4194e8f Mon Sep 17 00:00:00 2001 From: NidhaNureen Date: Thu, 17 Apr 2025 00:51:27 +1200 Subject: [PATCH 2/8] fixed doctests to be less excessive --- .../binary_tree/lowest_common_ancestor.py | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 9b59389456b7..a2a14d04f035 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -11,10 +11,8 @@ def swap(a: int, b: int) -> tuple[int, int]: Return a tuple (b, a) when given two integers a and b >>> swap(2,3) (3, 2) - >>> swap(3,4) - (4, 3) - >>> swap(67, 12) - (12, 67) + >>> swap(3,-4) + (-4, 3) """ a ^= b b ^= a @@ -35,6 +33,13 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: >>> parent[2] [0, 0, 0, 0, 0, 0, 0] + >>> max_node = 1 + >>> parent = [[0, 0]] + [[0] * 2 for _ in range(19)] + >>> parent = create_sparse(max_node, parent) + >>> parent[0] + [0, 0] + >>> parent[1] + [0, 0] """ j = 1 while (1 << j) < max_node: @@ -52,21 +57,16 @@ def lowest_common_ancestor( Return the lowest common ancestor between u and v >>> level = [-1, 0, 1, 1, 2, 2, 2] - >>> parent = [[0, 0, 1, 1, 2, 2, 3],[0, 0, 0, 0, 1, 1, 1]] + [[0] * 7 for _ in range(17)] + >>> parent = [[0, 0, 1, 1, 2, 2, 3],[0, 0, 0, 0, 1, 1, 1]] + \ + [[0] * 7 for _ in range(17)] >>> lowest_common_ancestor(4, 5, level, parent) 2 - >>> lowest_common_ancestor(3, 6, level, parent) - 3 >>> lowest_common_ancestor(4, 6, level, parent) 1 - >>> lowest_common_ancestor(5, 6, level, parent) - 1 >>> lowest_common_ancestor(2, 3, level, parent) 1 >>> lowest_common_ancestor(6, 6, level, parent) 6 - >>> lowest_common_ancestor(1, 3, level, parent) - 1 """ # u must be deeper in the tree than v if level[u] < level[v]: @@ -86,8 +86,6 @@ def lowest_common_ancestor( return parent[0][u] - - # runs a breadth first search from root node of the tree def breadth_first_search( level: list[int], @@ -108,12 +106,8 @@ def breadth_first_search( [-1, 0, 1, 1, 2, 2, 2] >>> parent[0] [0, 0, 1, 1, 2, 2, 3] - >>> parent[1] - [0, 0, 0, 0, 0, 0, 0] - >>> parent[2] - [0, 0, 0, 0, 0, 0, 0] - # Edge case: graph with one node + >>> level = [-1] * 2 >>> parent = [[0] * 2 for _ in range(20)] >>> graph = {1: []} @@ -122,8 +116,6 @@ def breadth_first_search( [-1, 0] >>> parent[0] [0, 0] - >>> parent[1] - [0, 0] """ level[root] = 0 q: Queue[int] = Queue(maxsize=max_node) From 03c6154948a515e9ec03a3dc677d60354e899a8b Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:14:30 +0300 Subject: [PATCH 3/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index a2a14d04f035..88474f2bdf62 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -11,6 +11,10 @@ def swap(a: int, b: int) -> tuple[int, int]: Return a tuple (b, a) when given two integers a and b >>> swap(2,3) (3, 2) + >>> swap(3,4) + (4, 3) + >>> swap(67, 12) + (12, 67) >>> swap(3,-4) (-4, 3) """ From 76a1eba4b3af334caaedd3b334ba836796c3aa4d Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:17:50 +0300 Subject: [PATCH 4/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 88474f2bdf62..3563d5f85161 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -29,7 +29,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: creating sparse table which saves each nodes 2^i-th parent >>> max_node = 6 >>> parent = [[0, 0, 1, 1, 2, 2, 3]] + [[0] * 7 for _ in range(19)] - >>> parent = create_sparse(max_node, parent) + >>> parent = create_sparse(max_node=max_node, parent=parent) >>> parent[0] [0, 0, 1, 1, 2, 2, 3] >>> parent[1] @@ -39,7 +39,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: >>> max_node = 1 >>> parent = [[0, 0]] + [[0] * 2 for _ in range(19)] - >>> parent = create_sparse(max_node, parent) + >>> parent = create_sparse(max_node=max_node, parent=parent) >>> parent[0] [0, 0] >>> parent[1] From 9466e87e6cbce16b03f350c60020f939d063ef36 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:20:18 +0300 Subject: [PATCH 5/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 3563d5f85161..d7d662b4438d 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -63,13 +63,13 @@ def lowest_common_ancestor( >>> level = [-1, 0, 1, 1, 2, 2, 2] >>> parent = [[0, 0, 1, 1, 2, 2, 3],[0, 0, 0, 0, 1, 1, 1]] + \ [[0] * 7 for _ in range(17)] - >>> lowest_common_ancestor(4, 5, level, parent) + >>> lowest_common_ancestor(u=4, v=5, level=level, parent=parent) 2 - >>> lowest_common_ancestor(4, 6, level, parent) + >>> lowest_common_ancestor(u=4, v=6, level=level, parent=parent) 1 - >>> lowest_common_ancestor(2, 3, level, parent) + >>> lowest_common_ancestor(u=2, v=3, level=level, parent=parent) 1 - >>> lowest_common_ancestor(6, 6, level, parent) + >>> lowest_common_ancestor(u=6, v=6, level=level, parent=parent) 6 """ # u must be deeper in the tree than v From 5afd34c842ee9f70dd0df4817d162a053a5ad943 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:24:32 +0300 Subject: [PATCH 6/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index d7d662b4438d..9fa81bb7948d 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -105,7 +105,7 @@ def breadth_first_search( >>> level = [-1] * 7 >>> parent = [[0] * 7 for _ in range(20)] >>> graph = {1: [2, 3], 2: [4, 5], 3: [6], 4: [], 5: [], 6: []} - >>> level, parent = breadth_first_search(level, parent, 6, graph, 1) + >>> level, parent = breadth_first_search(level=level, parent=parent, max_node=6, graph=graph, root=1) >>> level [-1, 0, 1, 1, 2, 2, 2] >>> parent[0] From 3affce40f085a767828f1c5ed67b64e3975e9bf5 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:25:22 +0300 Subject: [PATCH 7/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 9fa81bb7948d..0e22e860be71 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -115,7 +115,7 @@ def breadth_first_search( >>> level = [-1] * 2 >>> parent = [[0] * 2 for _ in range(20)] >>> graph = {1: []} - >>> level, parent = breadth_first_search(level, parent, 1, graph, 1) + >>> level, parent = breadth_first_search(level=level, parent=parent, max_node=1, graph=graph, root=1) >>> level [-1, 0] >>> parent[0] From dfff17a7d875dab1036594e32d0c92df16852076 Mon Sep 17 00:00:00 2001 From: Maxim Smolskiy Date: Sat, 10 May 2025 14:27:12 +0300 Subject: [PATCH 8/8] Update lowest_common_ancestor.py --- data_structures/binary_tree/lowest_common_ancestor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index 0e22e860be71..ea0e31256903 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -105,7 +105,8 @@ def breadth_first_search( >>> level = [-1] * 7 >>> parent = [[0] * 7 for _ in range(20)] >>> graph = {1: [2, 3], 2: [4, 5], 3: [6], 4: [], 5: [], 6: []} - >>> level, parent = breadth_first_search(level=level, parent=parent, max_node=6, graph=graph, root=1) + >>> level, parent = breadth_first_search( + ... level=level, parent=parent, max_node=6, graph=graph, root=1) >>> level [-1, 0, 1, 1, 2, 2, 2] >>> parent[0] @@ -115,7 +116,8 @@ def breadth_first_search( >>> level = [-1] * 2 >>> parent = [[0] * 2 for _ in range(20)] >>> graph = {1: []} - >>> level, parent = breadth_first_search(level=level, parent=parent, max_node=1, graph=graph, root=1) + >>> level, parent = breadth_first_search( + ... level=level, parent=parent, max_node=1, graph=graph, root=1) >>> level [-1, 0] >>> parent[0]