From c96702cdf4e8bf91329df11adcc9e410e20e48f8 Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 25 Oct 2023 16:41:55 -0700 Subject: [PATCH 1/4] Add doctests and type hints --- graphs/tarjans_scc.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/graphs/tarjans_scc.py b/graphs/tarjans_scc.py index dfd2e52704d5..2824308054ed 100644 --- a/graphs/tarjans_scc.py +++ b/graphs/tarjans_scc.py @@ -1,7 +1,7 @@ from collections import deque -def tarjan(g): +def tarjan(g: list[list[int]]) -> list[list[int]]: """ Tarjan's algo for finding strongly connected components in a directed graph @@ -19,15 +19,30 @@ def tarjan(g): Complexity: strong_connect() is called at most once for each node and has a complexity of O(|E|) as it is DFS. Therefore this has complexity O(|V| + |E|) for a graph G = (V, E) + + >>> tarjan([[2, 3, 4], [2, 3, 4], [0, 1, 3], [0, 1, 2], [1]]) + [[4, 3, 1, 2, 0]] + >>> tarjan([[], [], [], []]) + [[0], [1], [2], [3]] + >>> a = [0, 1, 2, 3, 4, 5, 4] + >>> b = [1, 0, 3, 2, 5, 4, 0] + >>> n = 7 + >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == \ + sorted(tarjan(create_graph(n, list(zip(a[::-1], b[::-1]))))) + True + >>> a = [0, 1, 2, 3, 4, 5, 6] + >>> b = [0, 1, 2, 3, 4, 5, 6] + >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) + [[0], [1], [2], [3], [4], [5], [6]] """ n = len(g) - stack = deque() + stack: deque[int] = deque() on_stack = [False for _ in range(n)] index_of = [-1 for _ in range(n)] lowlink_of = index_of[:] - def strong_connect(v, index, components): + def strong_connect(v: int, index: int, components: list[list[int]]) -> int: index_of[v] = index # the number when this node is seen lowlink_of[v] = index # lowest rank node reachable from here index += 1 @@ -57,7 +72,7 @@ def strong_connect(v, index, components): components.append(component) return index - components = [] + components: list[list[int]] = [] for v in range(n): if index_of[v] == -1: strong_connect(v, 0, components) @@ -65,8 +80,16 @@ def strong_connect(v, index, components): return components -def create_graph(n, edges): - g = [[] for _ in range(n)] +def create_graph(n: int, edges: list[tuple[int, int]]) -> list[list[int]]: + """ + >>> n = 7 + >>> source = [0, 0, 1, 2, 3, 3, 4, 4, 6] + >>> target = [1, 3, 2, 0, 1, 4, 5, 6, 5] + >>> edges = list(zip(source, target)) + >>> create_graph(n, edges) + [[1, 3], [2], [0], [1, 4], [5, 6], [], [5]] + """ + g: list[list[int]] = [[] for _ in range(n)] for u, v in edges: g[u].append(v) return g From 0f036561fe141a3b00c71d8a1d069d014771a727 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 26 Oct 2023 02:39:22 -0400 Subject: [PATCH 2/4] Apply suggestions from code review --- graphs/tarjans_scc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphs/tarjans_scc.py b/graphs/tarjans_scc.py index 2824308054ed..1bae51a5e2f3 100644 --- a/graphs/tarjans_scc.py +++ b/graphs/tarjans_scc.py @@ -27,8 +27,8 @@ def tarjan(g: list[list[int]]) -> list[list[int]]: >>> a = [0, 1, 2, 3, 4, 5, 4] >>> b = [1, 0, 3, 2, 5, 4, 0] >>> n = 7 - >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == \ - sorted(tarjan(create_graph(n, list(zip(a[::-1], b[::-1]))))) + >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == + ... sorted(tarjan(create_graph(n, list(reversed(zip(a, b)))))) True >>> a = [0, 1, 2, 3, 4, 5, 6] >>> b = [0, 1, 2, 3, 4, 5, 6] From f80b80be8e93a143663170a519779d11c82f7a6e Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 26 Oct 2023 02:48:30 -0400 Subject: [PATCH 3/4] Update tarjans_scc.py --- graphs/tarjans_scc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphs/tarjans_scc.py b/graphs/tarjans_scc.py index 1bae51a5e2f3..f47478075a7f 100644 --- a/graphs/tarjans_scc.py +++ b/graphs/tarjans_scc.py @@ -27,8 +27,8 @@ def tarjan(g: list[list[int]]) -> list[list[int]]: >>> a = [0, 1, 2, 3, 4, 5, 4] >>> b = [1, 0, 3, 2, 5, 4, 0] >>> n = 7 - >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == - ... sorted(tarjan(create_graph(n, list(reversed(zip(a, b)))))) + >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == sorted( + ... tarjan(create_graph(n, list(reversed(zip(a, b)))))) True >>> a = [0, 1, 2, 3, 4, 5, 6] >>> b = [0, 1, 2, 3, 4, 5, 6] From 8e507d84701aa7c70ee4756acf684d6e146b0392 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Thu, 26 Oct 2023 02:53:22 -0400 Subject: [PATCH 4/4] Update tarjans_scc.py --- graphs/tarjans_scc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/tarjans_scc.py b/graphs/tarjans_scc.py index f47478075a7f..a75dc4d2ca95 100644 --- a/graphs/tarjans_scc.py +++ b/graphs/tarjans_scc.py @@ -28,7 +28,7 @@ def tarjan(g: list[list[int]]) -> list[list[int]]: >>> b = [1, 0, 3, 2, 5, 4, 0] >>> n = 7 >>> sorted(tarjan(create_graph(n, list(zip(a, b))))) == sorted( - ... tarjan(create_graph(n, list(reversed(zip(a, b)))))) + ... tarjan(create_graph(n, list(zip(a[::-1], b[::-1]))))) True >>> a = [0, 1, 2, 3, 4, 5, 6] >>> b = [0, 1, 2, 3, 4, 5, 6]