mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-03-03 21:38:40 +00:00
modified
This commit is contained in:
parent
419ccccf24
commit
68cd62c1be
@ -1,11 +1,14 @@
|
|||||||
|
# https://en.wikipedia.org/wiki/Lowest_common_ancestor
|
||||||
|
# https://en.wikipedia.org/wiki/Breadth-first_search
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
|
||||||
|
|
||||||
def swap(a: int, b: int) -> tuple[int, int]:
|
def swap(a: int, b: int) -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
Return a tuple (b, a) when given two integers a and b.
|
Return a tuple (b, a) when given two integers a and b
|
||||||
|
|
||||||
>>> swap(2,3)
|
>>> swap(2,3)
|
||||||
(3, 2)
|
(3, 2)
|
||||||
>>> swap(3,4)
|
>>> swap(3,4)
|
||||||
@ -52,23 +55,17 @@ def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]:
|
|||||||
return parent
|
return parent
|
||||||
|
|
||||||
|
|
||||||
|
# returns lca of node u,v
|
||||||
def lowest_common_ancestor(
|
def lowest_common_ancestor(
|
||||||
u: int, v: int, level: list[int], parent: list[list[int]]
|
u: int, v: int, level: list[int], parent: list[list[int]]
|
||||||
) -> int:
|
) -> int:
|
||||||
"""
|
"""
|
||||||
Return the lowest common ancestor (LCA) of nodes u and v in a tree.
|
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
|
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, and ``parent`` is a sparse table where parent[0][i] is the direct parent
|
||||||
of node i.
|
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:
|
>>> # Consider a simple tree:
|
||||||
>>> # 1
|
>>> # 1
|
||||||
>>> # / \\
|
>>> # / \\
|
||||||
@ -81,23 +78,25 @@ def lowest_common_ancestor(
|
|||||||
>>> lowest_common_ancestor(2, 2, level, parent)
|
>>> lowest_common_ancestor(2, 2, level, parent)
|
||||||
2
|
2
|
||||||
"""
|
"""
|
||||||
# Ensure u is at least as deep as v.
|
# u must be deeper in the tree than v
|
||||||
if level[u] < level[v]:
|
if level[u] < level[v]:
|
||||||
u, v = swap(u, 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):
|
for i in range(18, -1, -1):
|
||||||
if level[u] - (1 << i) >= level[v]:
|
if level[u] - (1 << i) >= level[v]:
|
||||||
u = parent[i][u]
|
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:
|
if u == v:
|
||||||
return u
|
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):
|
for i in range(18, -1, -1):
|
||||||
if parent[i][u] not in [0, parent[i][v]]:
|
if parent[i][u] not in [0, parent[i][v]]:
|
||||||
u, v = parent[i][u], parent[i][v]
|
u, v = parent[i][u], parent[i][v]
|
||||||
|
# returning longest common ancestor of u,v
|
||||||
return parent[0][u]
|
return parent[0][u]
|
||||||
|
|
||||||
|
|
||||||
|
# runs a breadth first search from root node of the tree
|
||||||
def breadth_first_search(
|
def breadth_first_search(
|
||||||
level: list[int],
|
level: list[int],
|
||||||
parent: list[list[int]],
|
parent: list[list[int]],
|
||||||
@ -143,7 +142,6 @@ def main() -> None:
|
|||||||
sparse table and compute several lowest common ancestors.
|
sparse table and compute several lowest common ancestors.
|
||||||
|
|
||||||
The sample tree used is:
|
The sample tree used is:
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
1
|
1
|
||||||
/ | \
|
/ | \
|
||||||
@ -153,17 +151,6 @@ def main() -> None:
|
|||||||
/ \\ | / \\
|
/ \\ | / \\
|
||||||
9 10 11 12 13
|
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:
|
The expected lowest common ancestors are:
|
||||||
- LCA(1, 3) --> 1
|
- LCA(1, 3) --> 1
|
||||||
- LCA(5, 6) --> 1
|
- LCA(5, 6) --> 1
|
||||||
@ -187,7 +174,9 @@ def main() -> None:
|
|||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
max_node = 13
|
max_node = 13
|
||||||
|
# initializing with 0
|
||||||
parent = [[0 for _ in range(max_node + 10)] for _ in range(20)]
|
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)]
|
level = [-1 for _ in range(max_node + 10)]
|
||||||
graph: dict[int, list[int]] = {
|
graph: dict[int, list[int]] = {
|
||||||
1: [2, 3, 4],
|
1: [2, 3, 4],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user