From 06485a2f014d1d1f9a3cb0fe9a7401a3db79ae10 Mon Sep 17 00:00:00 2001
From: Siddhant Jain <sjain35@buffalo.edu>
Date: Mon, 13 Jan 2025 16:41:43 -0500
Subject: [PATCH 1/9] Added doctests to Lowest_common_ancestor.py

---
 .../binary_tree/lowest_common_ancestor.py     | 108 +++++++++++++++++-
 1 file changed, 104 insertions(+), 4 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index 651037703b95..830f3f85c491 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -24,7 +24,22 @@ 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
+    Create a sparse table which saves each node's 2^i-th parent.
+
+    >>> max_node = 5
+    >>> parent = [
+    ...     [0, 0, 1, 1, 2, 2],  # 2^0-th parents
+    ...     [0, 0, 0, 0, 1, 1]   # 2^1-th parents
+    ... ]
+    >>> create_sparse(max_node, parent)
+    [[0, 0, 1, 1, 2, 2], [0, 0, 0, 0, 1, 1]]
+    >>> max_node = 3
+    >>> parent = [
+    ...     [0, 0, 1, 1],  # 2^0-th parents
+    ...     [0, 0, 0, 0]   # 2^1-th parents
+    ... ]
+    >>> create_sparse(max_node, parent)
+    [[0, 0, 1, 1], [0, 0, 0, 0]]
     """
     j = 1
     while (1 << j) < max_node:
@@ -38,6 +53,46 @@ 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 of nodes u and v.
+
+    >>> max_node = 13
+    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
+    >>> level = [-1 for _ in range(max_node + 10)]
+    >>> graph = {
+    ...     1: [2, 3, 4],
+    ...     2: [5],
+    ...     3: [6, 7],
+    ...     4: [8],
+    ...     5: [9, 10],
+    ...     6: [11],
+    ...     7: [],
+    ...     8: [12, 13],
+    ...     9: [],
+    ...     10: [],
+    ...     11: [],
+    ...     12: [],
+    ...     13: [],
+    ... }
+    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
+    >>> parent = create_sparse(max_node, parent)
+    >>> lowest_common_ancestor(1, 3, level, parent)
+    1
+    >>> lowest_common_ancestor(5, 6, level, parent)
+    1
+    >>> lowest_common_ancestor(7, 11, level, parent)
+    1
+    >>> lowest_common_ancestor(6, 7, level, parent)
+    3
+    >>> lowest_common_ancestor(4, 12, level, parent)
+    4
+    >>> lowest_common_ancestor(8, 8, level, parent)
+    8
+    >>> lowest_common_ancestor(9, 10, level, parent)
+    5
+    >>> lowest_common_ancestor(12, 13, level, parent)
+    8
+    """
     # u must be deeper in the tree than v
     if level[u] < level[v]:
         u, v = swap(u, v)
@@ -65,9 +120,54 @@ def breadth_first_search(
     root: int = 1,
 ) -> tuple[list[int], list[list[int]]]:
     """
-    sets every nodes direct parent
-    parent of root node is set to 0
-    calculates depth of each node from root node
+    Perform a breadth-first search from the root node of the tree.
+    Sets every node's direct parent and calculates the depth of each node from the root.
+
+    >>> max_node = 5
+    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
+    >>> level = [-1 for _ in range(max_node + 10)]
+    >>> graph = {
+    ...     1: [2, 3],
+    ...     2: [4],
+    ...     3: [5],
+    ...     4: [],
+    ...     5: []
+    ... }
+    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
+    >>> level[:6]
+    [ -1, 0, 1, 1, 2, 2]
+    >>> parent[0][1] == 0
+    True
+    >>> parent[0][2] == 1
+    True
+    >>> parent[0][3] == 1
+    True
+    >>> parent[0][4] == 2
+    True
+    >>> parent[0][5] == 3
+    True
+
+    >>> # Test with disconnected graph
+    >>> max_node = 4
+    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
+    >>> level = [-1 for _ in range(max_node + 10)]
+    >>> graph = {
+    ...     1: [2],
+    ...     2: [],
+    ...     3: [4],
+    ...     4: []
+    ... }
+    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
+    >>> level[:5]
+    [ -1, 0, 1, -1, -1]
+    >>> parent[0][1] == 0
+    True
+    >>> parent[0][2] == 1
+    True
+    >>> parent[0][3] == 0
+    True
+    >>> parent[0][4] == 3
+    True
     """
     level[root] = 0
     q: Queue[int] = Queue(maxsize=max_node)

From b74d7f53925cee24bddd436d6a7d6766d573a17e Mon Sep 17 00:00:00 2001
From: Siddhant Jain <sjain35@buffalo.edu>
Date: Mon, 13 Jan 2025 16:56:22 -0500
Subject: [PATCH 2/9] Modified doctest

---
 .../binary_tree/lowest_common_ancestor.py     | 218 +++++++++---------
 1 file changed, 104 insertions(+), 114 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index 830f3f85c491..f34e6f7728c8 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -2,16 +2,16 @@
 # https://en.wikipedia.org/wiki/Breadth-first_search
 
 from __future__ import annotations
-
 from queue import Queue
 
 
 def swap(a: int, b: int) -> tuple[int, int]:
     """
-    Return a tuple (b, a) when given two integers a and b
-    >>> swap(2,3)
+    Return a tuple (b, a) when given two integers a and b.
+
+    >>> swap(2, 3)
     (3, 2)
-    >>> swap(3,4)
+    >>> swap(3, 4)
     (4, 3)
     >>> swap(67, 12)
     (12, 67)
@@ -24,22 +24,30 @@ def swap(a: int, b: int) -> tuple[int, int]:
 
 def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     """
-    Create a sparse table which saves each node's 2^i-th parent.
-
-    >>> max_node = 5
-    >>> parent = [
-    ...     [0, 0, 1, 1, 2, 2],  # 2^0-th parents
-    ...     [0, 0, 0, 0, 1, 1]   # 2^1-th parents
-    ... ]
-    >>> create_sparse(max_node, parent)
-    [[0, 0, 1, 1, 2, 2], [0, 0, 0, 0, 1, 1]]
-    >>> max_node = 3
-    >>> parent = [
-    ...     [0, 0, 1, 1],  # 2^0-th parents
-    ...     [0, 0, 0, 0]   # 2^1-th parents
-    ... ]
-    >>> create_sparse(max_node, parent)
-    [[0, 0, 1, 1], [0, 0, 0, 0]]
+    Create a sparse table that saves each node's 2^i-th parent.
+
+    The given `parent` table should have the direct parent of each node in row 0.
+    The function then fills in parent[j][i] = parent[j-1][parent[j-1][i]] for each j where 2^j < max_node.
+
+    For example, consider a small tree where:
+      - Node 1 is the root (its parent is 0),
+      - Nodes 2 and 3 have parent 1.
+    
+    We set up the parent table for only two levels (row 0 and row 1)
+    for max_node = 3. (Note that in practice the table has many rows.)
+
+    >>> # Create an initial parent table with 2 rows and indices 0..3.
+    >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, node2 and 3's parent=1.
+    >>> parent1 = [0, 0, 0, 0]
+    >>> parent = [parent0, parent1]
+    >>> # We need at least (1 << j) < max_node holds only for j = 1 here since (1 << 1)=2 < 3 and (1 << 2)=4 !< 3.
+    >>> sparse = create_sparse(3, parent)
+    >>> sparse[1][1], sparse[1][2], sparse[1][3]
+    (0, 0, 0)
+    >>> # Explanation:
+    >>> # For node 1: parent[1][1] = parent[0][parent[0][1]] = parent[0][0] = 0.
+    >>> # For node 2: parent[1][2] = parent[0][parent[0][2]] = parent[0][1] = 0.
+    >>> # For node 3: parent[1][3] = parent[0][parent[0][3]] = parent[0][1] = 0.
     """
     j = 1
     while (1 << j) < max_node:
@@ -49,69 +57,46 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     return parent
 
 
-# returns lca of node u,v
 def lowest_common_ancestor(
     u: int, v: int, level: list[int], parent: list[list[int]]
 ) -> int:
     """
-    Return the lowest common ancestor of nodes u and v.
-
-    >>> max_node = 13
-    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
-    >>> level = [-1 for _ in range(max_node + 10)]
-    >>> graph = {
-    ...     1: [2, 3, 4],
-    ...     2: [5],
-    ...     3: [6, 7],
-    ...     4: [8],
-    ...     5: [9, 10],
-    ...     6: [11],
-    ...     7: [],
-    ...     8: [12, 13],
-    ...     9: [],
-    ...     10: [],
-    ...     11: [],
-    ...     12: [],
-    ...     13: [],
-    ... }
-    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
-    >>> parent = create_sparse(max_node, parent)
-    >>> lowest_common_ancestor(1, 3, level, parent)
-    1
-    >>> lowest_common_ancestor(5, 6, level, parent)
+    Return the lowest common ancestor (LCA) of nodes u and v in a tree.
+
+    The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
+    and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
+    
+    >>> # Consider a simple tree:
+    >>> #       1
+    >>> #      / \\
+    >>> #     2   3
+    >>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0,0,1,1]
+    >>> level = [-1, 0, 1, 1]  # index 0 is dummy
+    >>> parent = [[0, 0, 1, 1]] + [[0, 0, 0, 0] for _ in range(19)]
+    >>> lowest_common_ancestor(2, 3, level, parent)
     1
-    >>> lowest_common_ancestor(7, 11, level, parent)
-    1
-    >>> lowest_common_ancestor(6, 7, level, parent)
-    3
-    >>> lowest_common_ancestor(4, 12, level, parent)
-    4
-    >>> lowest_common_ancestor(8, 8, level, parent)
-    8
-    >>> lowest_common_ancestor(9, 10, level, parent)
-    5
-    >>> lowest_common_ancestor(12, 13, level, parent)
-    8
+    >>> # LCA of a node with itself is itself.
+    >>> lowest_common_ancestor(2, 2, level, parent)
+    2
     """
-    # u must be deeper in the tree than v
+    # Ensure u is at least as deep as v.
     if level[u] < level[v]:
         u, v = swap(u, v)
-    # making depth of u same as depth of v
+    # Bring u up to the same level as v.
     for i in range(18, -1, -1):
         if level[u] - (1 << i) >= level[v]:
             u = parent[i][u]
-    # at the same depth if u==v that mean lca is found
+    # If they are the same, we've found the LCA.
     if u == v:
         return u
-    # moving both nodes upwards till lca in found
+    # Move u and v up together until the LCA is found.
     for i in range(18, -1, -1):
         if parent[i][u] not in [0, parent[i][v]]:
             u, v = parent[i][u], parent[i][v]
-    # returning longest common ancestor of u,v
+    # Return the parent (direct ancestor) which is the LCA.
     return parent[0][u]
 
 
-# runs a breadth first search from root node of the tree
 def breadth_first_search(
     level: list[int],
     parent: list[list[int]],
@@ -120,54 +105,23 @@ def breadth_first_search(
     root: int = 1,
 ) -> tuple[list[int], list[list[int]]]:
     """
-    Perform a breadth-first search from the root node of the tree.
-    Sets every node's direct parent and calculates the depth of each node from the root.
-
-    >>> max_node = 5
-    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
-    >>> level = [-1 for _ in range(max_node + 10)]
-    >>> graph = {
-    ...     1: [2, 3],
-    ...     2: [4],
-    ...     3: [5],
-    ...     4: [],
-    ...     5: []
-    ... }
-    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
-    >>> level[:6]
-    [ -1, 0, 1, 1, 2, 2]
-    >>> parent[0][1] == 0
-    True
-    >>> parent[0][2] == 1
-    True
-    >>> parent[0][3] == 1
-    True
-    >>> parent[0][4] == 2
-    True
-    >>> parent[0][5] == 3
-    True
-
-    >>> # Test with disconnected graph
-    >>> max_node = 4
-    >>> parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
-    >>> level = [-1 for _ in range(max_node + 10)]
-    >>> graph = {
-    ...     1: [2],
-    ...     2: [],
-    ...     3: [4],
-    ...     4: []
-    ... }
-    >>> level, parent = breadth_first_search(level, parent, max_node, graph, 1)
-    >>> level[:5]
-    [ -1, 0, 1, -1, -1]
-    >>> parent[0][1] == 0
-    True
-    >>> parent[0][2] == 1
-    True
-    >>> parent[0][3] == 0
-    True
-    >>> parent[0][4] == 3
-    True
+    Run a breadth-first search (BFS) from the root node of the tree.
+
+    Sets every node's direct parent (in parent[0]) and calculates the depth (level)
+    of each node from the root.
+
+    >>> # Consider a simple tree:
+    >>> #    1
+    >>> #   / \\
+    >>> #  2   3
+    >>> graph = {1: [2, 3], 2: [], 3: []}
+    >>> level = [-1] * 4   # index 0 is unused; nodes 1 to 3.
+    >>> parent = [[0] * 4 for _ in range(20)]
+    >>> new_level, new_parent = breadth_first_search(level, parent, 3, graph, root=1)
+    >>> new_level[1:4]
+    [0, 1, 1]
+    >>> new_parent[0][1:4]
+    [0, 1, 1]
     """
     level[root] = 0
     q: Queue[int] = Queue(maxsize=max_node)
@@ -183,10 +137,46 @@ def breadth_first_search(
 
 
 def main() -> None:
+    """
+    Run a BFS to set node depths and parents in a sample tree,
+    then create the sparse table and compute several lowest common ancestors.
+
+    The sample tree used is:
+    
+            1
+         /  |  \ 
+        2   3   4
+       /   / \\  \\
+      5   6   7  8
+     / \\  |     / \\
+    9  10  11   12 13
+
+    The expected lowest common ancestors are:
+      - LCA(1, 3)  --> 1
+      - LCA(5, 6)  --> 1
+      - LCA(7, 11) --> 3
+      - LCA(6, 7)  --> 3
+      - LCA(4, 12) --> 4
+      - LCA(8, 8)  --> 8
+
+    To test main() without it printing to the console, we capture the output.
+    
+    >>> import sys
+    >>> from io import StringIO
+    >>> backup = sys.stdout
+    >>> sys.stdout = StringIO()
+    >>> main()
+    >>> output = sys.stdout.getvalue()
+    >>> sys.stdout = backup
+    >>> 'LCA of node 1 and 3 is:  1' in output
+    True
+    >>> 'LCA of node 7 and 11 is:  3' in output
+    True
+    """
     max_node = 13
-    # initializing with 0
+    # initializing with 0; extra space is allocated.
     parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
-    # initializing with -1 which means every node is unvisited
+    # initializing with -1 which means every node is unvisited.
     level = [-1 for _ in range(max_node + 10)]
     graph: dict[int, list[int]] = {
         1: [2, 3, 4],

From 097e9c6149e80f095be1b3dbef1c04ff94a7325a Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2025 21:56:50 +0000
Subject: [PATCH 3/9] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 data_structures/binary_tree/lowest_common_ancestor.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index f34e6f7728c8..33fecb51907b 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -32,7 +32,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
-    
+
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
 
@@ -65,7 +65,7 @@ def lowest_common_ancestor(
 
     The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
     and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
-    
+
     >>> # Consider a simple tree:
     >>> #       1
     >>> #      / \\
@@ -142,9 +142,9 @@ def main() -> None:
     then create the sparse table and compute several lowest common ancestors.
 
     The sample tree used is:
-    
+
             1
-         /  |  \ 
+         /  |  \
         2   3   4
        /   / \\  \\
       5   6   7  8
@@ -160,7 +160,7 @@ def main() -> None:
       - LCA(8, 8)  --> 8
 
     To test main() without it printing to the console, we capture the output.
-    
+
     >>> import sys
     >>> from io import StringIO
     >>> backup = sys.stdout

From d6fff7504f4e99abd6a824f4e8bee13dd0a49772 Mon Sep 17 00:00:00 2001
From: Siddhant Jain <sjain35@buffalo.edu>
Date: Mon, 13 Jan 2025 16:59:00 -0500
Subject: [PATCH 4/9] Modified doctest

---
 .../binary_tree/lowest_common_ancestor.py     | 72 +++++++++----------
 1 file changed, 32 insertions(+), 40 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index f34e6f7728c8..938446946520 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -1,6 +1,3 @@
-# https://en.wikipedia.org/wiki/Lowest_common_ancestor
-# https://en.wikipedia.org/wiki/Breadth-first_search
-
 from __future__ import annotations
 from queue import Queue
 
@@ -25,29 +22,27 @@ def swap(a: int, b: int) -> tuple[int, int]:
 def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     """
     Create a sparse table that saves each node's 2^i-th parent.
-
-    The given `parent` table should have the direct parent of each node in row 0.
-    The function then fills in parent[j][i] = parent[j-1][parent[j-1][i]] for each j where 2^j < max_node.
-
+    
+    The given ``parent`` table should have the direct parent of each node in row 0.
+    This function fills in:
+    
+        parent[j][i] = parent[j - 1][parent[j - 1][i]]
+    
+    for each j where 2^j is less than max_node.
+    
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
     
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
-
-    >>> # Create an initial parent table with 2 rows and indices 0..3.
-    >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, node2 and 3's parent=1.
+    
+    >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, nodes 2 and 3's parent=1.
     >>> parent1 = [0, 0, 0, 0]
     >>> parent = [parent0, parent1]
-    >>> # We need at least (1 << j) < max_node holds only for j = 1 here since (1 << 1)=2 < 3 and (1 << 2)=4 !< 3.
     >>> sparse = create_sparse(3, parent)
-    >>> sparse[1][1], sparse[1][2], sparse[1][3]
+    >>> (sparse[1][1], sparse[1][2], sparse[1][3])
     (0, 0, 0)
-    >>> # Explanation:
-    >>> # For node 1: parent[1][1] = parent[0][parent[0][1]] = parent[0][0] = 0.
-    >>> # For node 2: parent[1][2] = parent[0][parent[0][2]] = parent[0][1] = 0.
-    >>> # For node 3: parent[1][3] = parent[0][parent[0][3]] = parent[0][1] = 0.
     """
     j = 1
     while (1 << j) < max_node:
@@ -62,20 +57,20 @@ def lowest_common_ancestor(
 ) -> int:
     """
     Return the lowest common ancestor (LCA) of nodes u and v in a tree.
-
-    The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
-    and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
+    
+    The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
+    of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
+    of node i.
     
     >>> # Consider a simple tree:
     >>> #       1
     >>> #      / \\
     >>> #     2   3
-    >>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0,0,1,1]
+    >>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0, 0, 1, 1]
     >>> level = [-1, 0, 1, 1]  # index 0 is dummy
     >>> parent = [[0, 0, 1, 1]] + [[0, 0, 0, 0] for _ in range(19)]
     >>> lowest_common_ancestor(2, 3, level, parent)
     1
-    >>> # LCA of a node with itself is itself.
     >>> lowest_common_ancestor(2, 2, level, parent)
     2
     """
@@ -93,7 +88,6 @@ def lowest_common_ancestor(
     for i in range(18, -1, -1):
         if parent[i][u] not in [0, parent[i][v]]:
             u, v = parent[i][u], parent[i][v]
-    # Return the parent (direct ancestor) which is the LCA.
     return parent[0][u]
 
 
@@ -106,10 +100,10 @@ def breadth_first_search(
 ) -> tuple[list[int], list[list[int]]]:
     """
     Run a breadth-first search (BFS) from the root node of the tree.
-
-    Sets every node's direct parent (in parent[0]) and calculates the depth (level)
-    of each node from the root.
-
+    
+    This sets each node's direct parent (stored in parent[0]) and calculates the
+    depth (level) of each node from the root.
+    
     >>> # Consider a simple tree:
     >>> #    1
     >>> #   / \\
@@ -138,19 +132,19 @@ def breadth_first_search(
 
 def main() -> None:
     """
-    Run a BFS to set node depths and parents in a sample tree,
-    then create the sparse table and compute several lowest common ancestors.
-
+    Run a BFS to set node depths and parents in a sample tree, then create the
+    sparse table and compute several lowest common ancestors.
+    
     The sample tree used is:
     
-            1
-         /  |  \ 
-        2   3   4
-       /   / \\  \\
-      5   6   7  8
-     / \\  |     / \\
-    9  10  11   12 13
-
+                1
+             /  |  \ 
+            2   3   4
+           /   / \\   \\
+          5   6   7   8
+         / \\   |    / \\
+        9  10  11  12  13
+    
     The expected lowest common ancestors are:
       - LCA(1, 3)  --> 1
       - LCA(5, 6)  --> 1
@@ -158,7 +152,7 @@ def main() -> None:
       - LCA(6, 7)  --> 3
       - LCA(4, 12) --> 4
       - LCA(8, 8)  --> 8
-
+    
     To test main() without it printing to the console, we capture the output.
     
     >>> import sys
@@ -174,9 +168,7 @@ def main() -> None:
     True
     """
     max_node = 13
-    # initializing with 0; extra space is allocated.
     parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
-    # initializing with -1 which means every node is unvisited.
     level = [-1 for _ in range(max_node + 10)]
     graph: dict[int, list[int]] = {
         1: [2, 3, 4],

From 18eed567e651b06887eb0bba2a93d1f61380a60d Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2025 22:02:43 +0000
Subject: [PATCH 5/9] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 .../binary_tree/lowest_common_ancestor.py     | 28 +++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index 2a729414da54..6ba53b0af98f 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -22,21 +22,21 @@ def swap(a: int, b: int) -> tuple[int, int]:
 def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     """
     Create a sparse table that saves each node's 2^i-th parent.
-    
+
     The given ``parent`` table should have the direct parent of each node in row 0.
     This function fills in:
-    
+
         parent[j][i] = parent[j - 1][parent[j - 1][i]]
-    
+
     for each j where 2^j is less than max_node.
-    
+
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
 
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
-    
+
     >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, nodes 2 and 3's parent=1.
     >>> parent1 = [0, 0, 0, 0]
     >>> parent = [parent0, parent1]
@@ -58,11 +58,11 @@ def lowest_common_ancestor(
     """
     Return the lowest common ancestor (LCA) of nodes u and v in a tree.
 <<<<<<< HEAD
-    
+
     The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
     of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
     of node i.
-    
+
 =======
 
     The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
@@ -107,10 +107,10 @@ def breadth_first_search(
 ) -> tuple[list[int], list[list[int]]]:
     """
     Run a breadth-first search (BFS) from the root node of the tree.
-    
+
     This sets each node's direct parent (stored in parent[0]) and calculates the
     depth (level) of each node from the root.
-    
+
     >>> # Consider a simple tree:
     >>> #    1
     >>> #   / \\
@@ -141,18 +141,18 @@ def main() -> None:
     """
     Run a BFS to set node depths and parents in a sample tree, then create the
     sparse table and compute several lowest common ancestors.
-    
+
     The sample tree used is:
 <<<<<<< HEAD
-    
+
                 1
-             /  |  \ 
+             /  |  \
             2   3   4
            /   / \\   \\
           5   6   7   8
          / \\   |    / \\
         9  10  11  12  13
-    
+
 =======
 
             1
@@ -171,7 +171,7 @@ def main() -> None:
       - LCA(6, 7)  --> 3
       - LCA(4, 12) --> 4
       - LCA(8, 8)  --> 8
-    
+
     To test main() without it printing to the console, we capture the output.
 
     >>> import sys

From 68cd62c1be72654f586613406e4a7cc54ffee9b5 Mon Sep 17 00:00:00 2001
From: Siddhant Jain <sjain35@buffalo.edu>
Date: Mon, 13 Jan 2025 17:06:15 -0500
Subject: [PATCH 6/9] modified

---
 .../binary_tree/lowest_common_ancestor.py     | 47 +++++++------------
 1 file changed, 18 insertions(+), 29 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index 2a729414da54..f99b6c721cf2 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -1,14 +1,17 @@
+# https://en.wikipedia.org/wiki/Lowest_common_ancestor
+# https://en.wikipedia.org/wiki/Breadth-first_search
+
 from __future__ import annotations
+
 from queue import Queue
 
 
 def swap(a: int, b: int) -> tuple[int, int]:
     """
-    Return a tuple (b, a) when given two integers a and b.
-
-    >>> swap(2, 3)
+    Return a tuple (b, a) when given two integers a and b
+    >>> swap(2,3)
     (3, 2)
-    >>> swap(3, 4)
+    >>> swap(3,4)
     (4, 3)
     >>> swap(67, 12)
     (12, 67)
@@ -33,7 +36,7 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
-
+    
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
     
@@ -52,23 +55,17 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     return parent
 
 
+# returns lca of node u,v
 def lowest_common_ancestor(
     u: int, v: int, level: list[int], parent: list[list[int]]
 ) -> int:
     """
     Return the lowest common ancestor (LCA) of nodes u and v in a tree.
-<<<<<<< HEAD
     
     The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
     of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
     of node i.
     
-=======
-
-    The lists `level` and `parent` must be precomputed. `level[i]` is the depth of node i,
-    and `parent` is a sparse table where parent[0][i] is the direct parent of node i.
-
->>>>>>> 097e9c6149e80f095be1b3dbef1c04ff94a7325a
     >>> # Consider a simple tree:
     >>> #       1
     >>> #      / \\
@@ -81,23 +78,25 @@ def lowest_common_ancestor(
     >>> lowest_common_ancestor(2, 2, level, parent)
     2
     """
-    # Ensure u is at least as deep as v.
+    # u must be deeper in the tree than v
     if level[u] < level[v]:
         u, v = swap(u, v)
-    # Bring u up to the same level as v.
+    # making depth of u same as depth of v
     for i in range(18, -1, -1):
         if level[u] - (1 << i) >= level[v]:
             u = parent[i][u]
-    # If they are the same, we've found the LCA.
+    # at the same depth if u==v that mean lca is found
     if u == v:
         return u
-    # Move u and v up together until the LCA is found.
+    # moving both nodes upwards till lca in found
     for i in range(18, -1, -1):
         if parent[i][u] not in [0, parent[i][v]]:
             u, v = parent[i][u], parent[i][v]
+    # returning longest common ancestor of u,v
     return parent[0][u]
 
 
+# runs a breadth first search from root node of the tree
 def breadth_first_search(
     level: list[int],
     parent: list[list[int]],
@@ -143,7 +142,6 @@ def main() -> None:
     sparse table and compute several lowest common ancestors.
     
     The sample tree used is:
-<<<<<<< HEAD
     
                 1
              /  |  \ 
@@ -153,17 +151,6 @@ def main() -> None:
          / \\   |    / \\
         9  10  11  12  13
     
-=======
-
-            1
-         /  |  \
-        2   3   4
-       /   / \\  \\
-      5   6   7  8
-     / \\  |     / \\
-    9  10  11   12 13
-
->>>>>>> 097e9c6149e80f095be1b3dbef1c04ff94a7325a
     The expected lowest common ancestors are:
       - LCA(1, 3)  --> 1
       - LCA(5, 6)  --> 1
@@ -173,7 +160,7 @@ def main() -> None:
       - LCA(8, 8)  --> 8
     
     To test main() without it printing to the console, we capture the output.
-
+    
     >>> import sys
     >>> from io import StringIO
     >>> backup = sys.stdout
@@ -187,7 +174,9 @@ def main() -> None:
     True
     """
     max_node = 13
+    # initializing with 0
     parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
+    # initializing with -1 which means every node is unvisited
     level = [-1 for _ in range(max_node + 10)]
     graph: dict[int, list[int]] = {
         1: [2, 3, 4],

From a82ab0900401ff0a3c616dcd260c6b855d27b7eb Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2025 22:08:27 +0000
Subject: [PATCH 7/9] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 .../binary_tree/lowest_common_ancestor.py     | 32 +++++++++----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index f99b6c721cf2..2ca489b1f2a8 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -25,21 +25,21 @@ def swap(a: int, b: int) -> tuple[int, int]:
 def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
     """
     Create a sparse table that saves each node's 2^i-th parent.
-    
+
     The given ``parent`` table should have the direct parent of each node in row 0.
     This function fills in:
-    
+
         parent[j][i] = parent[j - 1][parent[j - 1][i]]
-    
+
     for each j where 2^j is less than max_node.
-    
+
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
-    
+
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
-    
+
     >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, nodes 2 and 3's parent=1.
     >>> parent1 = [0, 0, 0, 0]
     >>> parent = [parent0, parent1]
@@ -61,11 +61,11 @@ def lowest_common_ancestor(
 ) -> int:
     """
     Return the lowest common ancestor (LCA) of nodes u and v in a tree.
-    
+
     The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
     of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
     of node i.
-    
+
     >>> # Consider a simple tree:
     >>> #       1
     >>> #      / \\
@@ -106,10 +106,10 @@ def breadth_first_search(
 ) -> tuple[list[int], list[list[int]]]:
     """
     Run a breadth-first search (BFS) from the root node of the tree.
-    
+
     This sets each node's direct parent (stored in parent[0]) and calculates the
     depth (level) of each node from the root.
-    
+
     >>> # Consider a simple tree:
     >>> #    1
     >>> #   / \\
@@ -140,17 +140,17 @@ def main() -> None:
     """
     Run a BFS to set node depths and parents in a sample tree, then create the
     sparse table and compute several lowest common ancestors.
-    
+
     The sample tree used is:
-    
+
                 1
-             /  |  \ 
+             /  |  \
             2   3   4
            /   / \\   \\
           5   6   7   8
          / \\   |    / \\
         9  10  11  12  13
-    
+
     The expected lowest common ancestors are:
       - LCA(1, 3)  --> 1
       - LCA(5, 6)  --> 1
@@ -158,9 +158,9 @@ def main() -> None:
       - LCA(6, 7)  --> 3
       - LCA(4, 12) --> 4
       - LCA(8, 8)  --> 8
-    
+
     To test main() without it printing to the console, we capture the output.
-    
+
     >>> import sys
     >>> from io import StringIO
     >>> backup = sys.stdout

From 0cd031a685b2c63d31775b9656f0b8ecf61ac6e3 Mon Sep 17 00:00:00 2001
From: Siddhant Jain <sjain35@buffalo.edu>
Date: Mon, 13 Jan 2025 17:21:30 -0500
Subject: [PATCH 8/9] modify doctest

---
 .../binary_tree/lowest_common_ancestor.py     | 53 +++++++++----------
 1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py
index f99b6c721cf2..8be08ac44f3f 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -23,24 +23,24 @@ def swap(a: int, b: int) -> tuple[int, int]:
 
 
 def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
-    """
+    r"""
     Create a sparse table that saves each node's 2^i-th parent.
-    
-    The given ``parent`` table should have the direct parent of each node in row 0.
-    This function fills in:
-    
+
+    The given ``parent`` table should have the direct parent of each node
+    in row 0. This function fills in:
+
         parent[j][i] = parent[j - 1][parent[j - 1][i]]
-    
+
     for each j where 2^j is less than max_node.
-    
+
     For example, consider a small tree where:
       - Node 1 is the root (its parent is 0),
       - Nodes 2 and 3 have parent 1.
-    
+
     We set up the parent table for only two levels (row 0 and row 1)
     for max_node = 3. (Note that in practice the table has many rows.)
-    
-    >>> parent0 = [0, 0, 1, 1]  # 0 is unused; node1's parent=0, nodes 2 and 3's parent=1.
+
+    >>> parent0 = [0, 0, 1, 1]
     >>> parent1 = [0, 0, 0, 0]
     >>> parent = [parent0, parent1]
     >>> sparse = create_sparse(3, parent)
@@ -59,18 +59,17 @@ 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:
-    """
+    r"""
     Return the lowest common ancestor (LCA) of nodes u and v in a tree.
-    
-    The lists ``level`` and ``parent`` must be precomputed. ``level[i]`` is the depth
-    of node i, and ``parent`` is a sparse table where parent[0][i] is the direct parent
-    of node i.
-    
+
+    The lists ``level`` and ``parent`` must be precomputed.
+
     >>> # Consider a simple tree:
     >>> #       1
     >>> #      / \\
     >>> #     2   3
-    >>> # With levels: level[1]=0, level[2]=1, level[3]=1 and parent[0]=[0, 0, 1, 1]
+    >>> # With levels: level[1]=0, level[2]=1, level[3]=1 and
+    >>> # parent[0]=[0, 0, 1, 1]
     >>> level = [-1, 0, 1, 1]  # index 0 is dummy
     >>> parent = [[0, 0, 1, 1]] + [[0, 0, 0, 0] for _ in range(19)]
     >>> lowest_common_ancestor(2, 3, level, parent)
@@ -104,12 +103,12 @@ def breadth_first_search(
     graph: dict[int, list[int]],
     root: int = 1,
 ) -> tuple[list[int], list[list[int]]]:
-    """
+    r"""
     Run a breadth-first search (BFS) from the root node of the tree.
-    
+
     This sets each node's direct parent (stored in parent[0]) and calculates the
     depth (level) of each node from the root.
-    
+
     >>> # Consider a simple tree:
     >>> #    1
     >>> #   / \\
@@ -117,7 +116,7 @@ def breadth_first_search(
     >>> graph = {1: [2, 3], 2: [], 3: []}
     >>> level = [-1] * 4   # index 0 is unused; nodes 1 to 3.
     >>> parent = [[0] * 4 for _ in range(20)]
-    >>> new_level, new_parent = breadth_first_search(level, parent, 3, graph, root=1)
+    >>> new_level, new_parent=breadth_first_search(level,parent,3,graph,root=1)
     >>> new_level[1:4]
     [0, 1, 1]
     >>> new_parent[0][1:4]
@@ -137,12 +136,12 @@ def breadth_first_search(
 
 
 def main() -> None:
-    """
+    r"""
     Run a BFS to set node depths and parents in a sample tree, then create the
     sparse table and compute several lowest common ancestors.
-    
+
     The sample tree used is:
-    
+
                 1
              /  |  \ 
             2   3   4
@@ -150,7 +149,7 @@ def main() -> None:
           5   6   7   8
          / \\   |    / \\
         9  10  11  12  13
-    
+
     The expected lowest common ancestors are:
       - LCA(1, 3)  --> 1
       - LCA(5, 6)  --> 1
@@ -158,9 +157,9 @@ def main() -> None:
       - LCA(6, 7)  --> 3
       - LCA(4, 12) --> 4
       - LCA(8, 8)  --> 8
-    
+
     To test main() without it printing to the console, we capture the output.
-    
+
     >>> import sys
     >>> from io import StringIO
     >>> backup = sys.stdout

From 51f78ae79e135d5195eaccacd78136128871b99c Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2025 22:23:02 +0000
Subject: [PATCH 9/9] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 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 8be08ac44f3f..c5b3ff3c26f7 100644
--- a/data_structures/binary_tree/lowest_common_ancestor.py
+++ b/data_structures/binary_tree/lowest_common_ancestor.py
@@ -143,7 +143,7 @@ def main() -> None:
     The sample tree used is:
 
                 1
-             /  |  \ 
+             /  |  \
             2   3   4
            /   / \\   \\
           5   6   7   8