From 11d2a47cc1d71df2b116e333fdca6d7c3d9a8d9d Mon Sep 17 00:00:00 2001 From: Kanika0306 Date: Sun, 23 Aug 2026 02:26:23 +0530 Subject: [PATCH 1/6] fix: sub-interval midpoint formula in ternary search --- searches/ternary_search.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 73e4b1ddc68b..6d1dc1a2107f 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -82,6 +82,11 @@ def ite_ternary_search(array: list[int], target: int) -> int: -1 >>> ite_ternary_search([.1, .4 , -.1], .1) 0 + >>> test_list_large = list(range(100)) + >>> ite_ternary_search(test_list_large, 65) + 65 + >>> ite_ternary_search(test_list_large, 105) + -1 """ left = 0 @@ -90,8 +95,8 @@ def ite_ternary_search(array: list[int], target: int) -> int: if right - left < precision: return lin_search(left, right, array, target) - one_third = (left + right) // 3 + 1 - two_third = 2 * (left + right) // 3 + 1 + one_third = left + (right - left) // 3 + two_third = right - (right - left) // 3 if array[one_third] == target: return one_third @@ -99,13 +104,13 @@ def ite_ternary_search(array: list[int], target: int) -> int: return two_third elif target < array[one_third]: - right = one_third - 1 + right = one_third elif array[two_third] < target: left = two_third + 1 else: left = one_third + 1 - right = two_third - 1 + right = two_third return -1 @@ -133,12 +138,19 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> -1 >>> rec_ternary_search(0, 3, [.1, .4 , -.1], .1) 0 + >>> test_list_large = list(range(100)) + >>> rec_ternary_search(0, len(test_list_large), test_list_large, 65) + 65 + >>> rec_ternary_search(20, 80, test_list_large, 65) + 65 + >>> rec_ternary_search(20, 80, test_list_large, 15) + -1 """ if left < right: if right - left < precision: return lin_search(left, right, array, target) - one_third = (left + right) // 3 + 1 - two_third = 2 * (left + right) // 3 + 1 + one_third = left + (right - left) // 3 + two_third = right - (right - left) // 3 if array[one_third] == target: return one_third @@ -146,11 +158,11 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> return two_third elif target < array[one_third]: - return rec_ternary_search(left, one_third - 1, array, target) + return rec_ternary_search(left, one_third, array, target) elif array[two_third] < target: return rec_ternary_search(two_third + 1, right, array, target) else: - return rec_ternary_search(one_third + 1, two_third - 1, array, target) + return rec_ternary_search(one_third + 1, two_third, array, target) else: return -1 @@ -165,9 +177,10 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> assert collection == sorted(collection), f"List must be ordered.\n{collection}." target = int(input("Enter the number to be found in the list:\n").strip()) result1 = ite_ternary_search(collection, target) - result2 = rec_ternary_search(0, len(collection) - 1, collection, target) + result2 = rec_ternary_search(0, len(collection), collection, target) if result2 != -1: print(f"Iterative search: {target} found at positions: {result1}") print(f"Recursive search: {target} found at positions: {result2}") else: print("Not found") + From 15bcd92c37cfa376b35bf66199e9c8c4c9fbcda1 Mon Sep 17 00:00:00 2001 From: Kanika0306 Date: Sun, 23 Aug 2026 02:50:10 +0530 Subject: [PATCH 2/6] fix(graphs): use deque and dict for kahns algorithm sparse vertices --- graphs/kahns_algorithm_topo.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index c956cf9f48fd..df5d1d72b9b8 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -1,3 +1,6 @@ +from collections import deque + + def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: """ Perform topological sorting of a Directed Acyclic Graph (DAG) @@ -21,10 +24,17 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: >>> graph_with_cycle = {0: [1], 1: [2], 2: [0]} >>> topological_sort(graph_with_cycle) + + >>> sparse_graph = {10: [20], 20: []} + >>> topological_sort(sparse_graph) + [10, 20] + + >>> sparse_cycle = {10: [20], 20: [10]} + >>> topological_sort(sparse_cycle) """ - indegree = [0] * len(graph) - queue = [] + indegree = dict.fromkeys(graph, 0) + queue: deque[int] = deque() topo_order = [] processed_vertices_count = 0 @@ -34,13 +44,13 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: indegree[i] += 1 # Add all vertices with 0 indegree to the queue - for i in range(len(indegree)): - if indegree[i] == 0: - queue.append(i) + for vertex, count in indegree.items(): + if count == 0: + queue.append(vertex) # Perform BFS while queue: - vertex = queue.pop(0) + vertex = queue.popleft() processed_vertices_count += 1 topo_order.append(vertex) From c070fac9471088b0cdbdffb20623887d318e0f01 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 21:21:39 +0000 Subject: [PATCH 3/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- searches/ternary_search.py | 1 - 1 file changed, 1 deletion(-) diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 6d1dc1a2107f..b51c839e1dbf 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -183,4 +183,3 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> print(f"Recursive search: {target} found at positions: {result2}") else: print("Not found") - From 67508934bc871239066201d00d3212da79d81349 Mon Sep 17 00:00:00 2001 From: Kanika0306 Date: Sat, 12 Sep 2026 13:38:19 +0530 Subject: [PATCH 4/6] perf(graphs): benchmark kahns queue performance --- graphs/kahns_algorithm_topo.py | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index df5d1d72b9b8..611b42f4005b 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -65,7 +65,42 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: return topo_order # valid topological ordering +def benchmark() -> None: + """ + Benchmark comparing list.pop(0) vs collections.deque.popleft(). + + Demonstrates the performance difference between O(n) list.pop(0) + and O(1) deque.popleft() operations for Kahn's algorithm queue. + """ + from timeit import timeit + + size = 50_000 + runs = 5 + + def use_list() -> None: + queue = list(range(size)) + while queue: + queue.pop(0) + + def use_deque() -> None: + queue = deque(range(size)) + while queue: + queue.popleft() + + list_time = timeit(use_list, number=runs) + deque_time = timeit(use_deque, number=runs) + + print(f"Benchmark results for queue size of {size} over {runs} runs:") + print(f"list.pop(0): {list_time:.5f} seconds") + print(f"deque.popleft(): {deque_time:.5f} seconds") + if deque_time > 0: + print( + f"deque.popleft() is {list_time / deque_time:.2f}x faster than list.pop(0)" + ) + + if __name__ == "__main__": import doctest doctest.testmod() + benchmark() From 9241eab3cd74d0e27d117516af0673f167e4ae0a Mon Sep 17 00:00:00 2001 From: Kanika0306 Date: Sat, 12 Sep 2026 14:40:04 +0530 Subject: [PATCH 5/6] perf(graphs): benchmark topological_sort queue performance --- graphs/kahns_algorithm_topo.py | 84 ++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index 611b42f4005b..128f3d43a10c 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -65,38 +65,72 @@ def topological_sort(graph: dict[int, list[int]]) -> list[int] | None: return topo_order # valid topological ordering +def _topological_sort_list_queue(graph: dict[int, list[int]]) -> list[int] | None: + """ + Pre-optimization implementation of Kahn's topological sort using list.pop(0). + + Used as a baseline for benchmark comparison against deque.popleft(). + """ + indegree = [0] * len(graph) + queue = [] + topo_order = [] + processed_vertices_count = 0 + + for values in graph.values(): + for i in values: + indegree[i] += 1 + + for i in range(len(indegree)): + if indegree[i] == 0: + queue.append(i) + + while queue: + vertex = queue.pop(0) + processed_vertices_count += 1 + topo_order.append(vertex) + + for neighbor in graph[vertex]: + indegree[neighbor] -= 1 + if indegree[neighbor] == 0: + queue.append(neighbor) + + if processed_vertices_count != len(graph): + return None + return topo_order + + def benchmark() -> None: """ - Benchmark comparing list.pop(0) vs collections.deque.popleft(). + Benchmark comparing topological_sort() (using deque.popleft) against + the pre-optimization baseline _topological_sort_list_queue() (using list.pop(0)). - Demonstrates the performance difference between O(n) list.pop(0) - and O(1) deque.popleft() operations for Kahn's algorithm queue. + Demonstrates the performance improvement of O(1) queue operations in Kahn's algorithm + on a graph with a large number of zero-indegree vertices. """ from timeit import timeit - size = 50_000 - runs = 5 + num_sources = 30_000 + graph = {i: [num_sources] for i in range(num_sources)} + graph[num_sources] = [] + + # Verify correctness: both implementations produce valid topological sorts + old_result = _topological_sort_list_queue(graph) + new_result = topological_sort(graph) + assert old_result is not None and new_result is not None + assert len(old_result) == len(new_result) == num_sources + 1 + assert set(old_result) == set(new_result) - def use_list() -> None: - queue = list(range(size)) - while queue: - queue.pop(0) - - def use_deque() -> None: - queue = deque(range(size)) - while queue: - queue.popleft() - - list_time = timeit(use_list, number=runs) - deque_time = timeit(use_deque, number=runs) - - print(f"Benchmark results for queue size of {size} over {runs} runs:") - print(f"list.pop(0): {list_time:.5f} seconds") - print(f"deque.popleft(): {deque_time:.5f} seconds") - if deque_time > 0: - print( - f"deque.popleft() is {list_time / deque_time:.2f}x faster than list.pop(0)" - ) + runs = 5 + old_time = timeit(lambda: _topological_sort_list_queue(graph), number=runs) + new_time = timeit(lambda: topological_sort(graph), number=runs) + + print( + f"Benchmark results for topological_sort with {num_sources} vertices over {runs} runs:" + ) + print(f"Pre-optimization (list.pop(0)): {old_time:.5f} seconds") + print(f"Current (deque.popleft): {new_time:.5f} seconds") + if new_time > 0: + print(f"Speedup ratio: {old_time / new_time:.2f}x faster") if __name__ == "__main__": From 57651d86579046c1950bd6afec68dd4c5309bc2e Mon Sep 17 00:00:00 2001 From: Kanika0306 Date: Sat, 12 Sep 2026 14:46:35 +0530 Subject: [PATCH 6/6] style(graphs): fix line length in kahns algorithm benchmark --- graphs/kahns_algorithm_topo.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphs/kahns_algorithm_topo.py b/graphs/kahns_algorithm_topo.py index 128f3d43a10c..268f03c6dda5 100644 --- a/graphs/kahns_algorithm_topo.py +++ b/graphs/kahns_algorithm_topo.py @@ -104,8 +104,8 @@ def benchmark() -> None: Benchmark comparing topological_sort() (using deque.popleft) against the pre-optimization baseline _topological_sort_list_queue() (using list.pop(0)). - Demonstrates the performance improvement of O(1) queue operations in Kahn's algorithm - on a graph with a large number of zero-indegree vertices. + Demonstrates the performance improvement of O(1) queue operations in + Kahn's algorithm on a graph with a large number of zero-indegree vertices. """ from timeit import timeit @@ -125,7 +125,8 @@ def benchmark() -> None: new_time = timeit(lambda: topological_sort(graph), number=runs) print( - f"Benchmark results for topological_sort with {num_sources} vertices over {runs} runs:" + f"Benchmark results for topological_sort with {num_sources} vertices " + f"over {runs} runs:" ) print(f"Pre-optimization (list.pop(0)): {old_time:.5f} seconds") print(f"Current (deque.popleft): {new_time:.5f} seconds")