From 69a4d715591030d4a56198a47b7d45278d7bb300 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 02:34:29 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Speed=20up=20method=20`Pat?= =?UTF-8?q?hFinder.find=5Fshortest=5Fpath`=20by=20246%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The optimized code achieves a 245% speedup through two key algorithmic improvements: **1. Replaced list-based queue with deque for O(1) operations** The original code used `queue.pop(0)` on a list, which is O(n) because it shifts all remaining elements. The line profiler shows this operation taking 15.4% of total time (2.327ms out of 15.129ms). The optimized version uses `collections.deque` with `popleft()`, which is O(1). This change alone eliminates the most expensive operation in the BFS traversal. **2. Eliminated path copying with parent tracking** The original code maintained complete paths by copying and extending them (`new_path = list(path)` + `new_path.append(neighbor)`), taking 19.7% of total time (12.6% + 7.1%). With thousands of nodes visited, this creates substantial memory allocation overhead. The optimized version stores only parent pointers in a dictionary and reconstructs the path once at the end, reducing both time and space complexity. **Performance characteristics by test case type:** - **Large linear graphs (1000+ nodes)**: Show the most dramatic improvement (400-433% faster) because they maximize the impact of both optimizations - many queue operations and long paths to copy - **Small graphs (2-5 nodes)**: Actually perform 17-50% slower due to the overhead of importing deque and managing the parent dictionary, but the absolute difference is negligible (microseconds) - **Dense/branching graphs**: Show moderate improvements (10-96% faster) as they benefit from reduced queue overhead but have shorter average path lengths - **Disconnected graphs**: Benefit significantly (286% faster) when no path exists, as the BFS explores many nodes before terminating The optimization transforms the algorithm from O(V²) time complexity (due to path copying) to O(V + E), making it scale much better for larger graphs while maintaining identical BFS shortest-path semantics. --- src/dsa/various.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/dsa/various.py b/src/dsa/various.py index 4356039..8beba89 100644 --- a/src/dsa/various.py +++ b/src/dsa/various.py @@ -1,4 +1,5 @@ import re +from collections import deque class Graph: @@ -96,21 +97,25 @@ def find_shortest_path(self, start: str, end: str) -> list[str]: if start not in self.graph or end not in self.graph: return [] - queue = [[start]] + queue = deque([start]) visited = set([start]) + parent = {start: None} while queue: - path = queue.pop(0) - node = path[-1] + node = queue.popleft() if node == end: - return path + # Reconstruct path backwards + path = [] + while node is not None: + path.append(node) + node = parent[node] + return path[::-1] for neighbor in self.graph.get(node, []): if neighbor not in visited: visited.add(neighbor) - new_path = list(path) - new_path.append(neighbor) - queue.append(new_path) + parent[neighbor] = node + queue.append(neighbor) return [] # No path found