BFS Breadth First Search on Graph in DSA Python - Time & Space Complexity
We want to understand how the time taken by BFS changes as the graph grows.
How does BFS's work increase when the graph has more nodes and edges?
Analyze the time complexity of the following code snippet.
from collections import deque
def bfs(graph, start):
visited = set()
queue = deque([start])
visited.add(start)
while queue:
node = queue.popleft()
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
This code explores all nodes reachable from the start node using BFS.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node and checking its neighbors.
- How many times: Each node is visited once; each edge is checked once.
As the graph grows, BFS visits more nodes and edges.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 10 + 15 = 25 operations |
| 100 nodes, 200 edges | About 100 + 200 = 300 operations |
| 1000 nodes, 5000 edges | About 1000 + 5000 = 6000 operations |
Pattern observation: Operations grow roughly with the sum of nodes and edges.
Time Complexity: O(n + m)
This means BFS takes time proportional to the number of nodes plus the number of edges in the graph.
[X] Wrong: "BFS always takes O(n²) time because it checks all pairs of nodes."
[OK] Correct: BFS only visits each node and edge once, not all pairs. So it depends on actual edges, not all possible pairs.
Understanding BFS time complexity helps you explain how graph searches scale in real problems.
"What if the graph is represented as an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
Step 1: Understand BFS traversal method
BFS explores nodes level by level, visiting all neighbors before moving deeper.Step 2: Identify the data structure used
To achieve level order traversal, BFS uses a queue to store nodes to visit next.Final Answer:
A queue to explore nodes level by level -> Option BQuick Check:
BFS uses queue = D [OK]
- Confusing BFS with DFS which uses stack
- Thinking BFS uses only a set without queue
- Assuming BFS uses recursion instead of queue
Solution
Step 1: Recall Python queue options for BFS
Python's collections module provides deque which supports fast append and pop from both ends.Step 2: Identify correct initialization
collections.Queue() does not exist; list() is slower for queue operations; set() is unordered.Final Answer:
queue = collections.deque() -> Option AQuick Check:
Use deque for BFS queue = collections.deque() [OK]
- Using list() which is slow for queue operations
- Trying collections.Queue() which is invalid
- Using set() which is unordered
graph = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F': []
}
from collections import deque
def bfs(graph, start):
visited = []
queue = deque([start])
while queue:
node = queue.popleft()
if node not in visited:
visited.append(node)
queue.extend(graph[node])
return visited
print(bfs(graph, 'A'))Solution
Step 1: Trace BFS starting from 'A'
Start with queue=['A'], visited=[] - Pop 'A', visited=['A'], add neighbors 'B','C' to queue - Pop 'B', visited=['A','B'], add 'D','E' - Pop 'C', visited=['A','B','C'], add 'F' - Pop 'D', visited=['A','B','C','D'], no neighbors - Pop 'E', visited=['A','B','C','D','E'], add 'F' - Pop 'F', visited=['A','B','C','D','E','F'], no neighborsStep 2: Confirm order of visited nodes
The visited order is ['A', 'B', 'C', 'D', 'E', 'F'] as BFS explores level by level.Final Answer:
['A', 'B', 'C', 'D', 'E', 'F'] -> Option CQuick Check:
BFS order from 'A' = ['A', 'B', 'C', 'D', 'E', 'F'] [OK]
- Mixing BFS with DFS order
- Not checking if node already visited before adding
- Assuming neighbors added in wrong order
def bfs(graph, start):
visited = set()
queue = [start]
while queue:
node = queue.pop()
if node not in visited:
visited.add(node)
queue.extend(graph[node])
return list(visited)Solution
Step 1: Understand queue behavior in BFS
BFS requires FIFO order, so nodes must be popped from the front of the queue.Step 2: Identify the bug in popping nodes
queue.pop() removes from the end (LIFO), which behaves like DFS. Changing to queue.pop(0) pops from front (FIFO).Final Answer:
Change queue.pop() to queue.pop(0) to pop from front -> Option AQuick Check:
Use pop(0) for BFS queue pop [OK]
- Using pop() which pops from end (DFS behavior)
- Confusing set and list for visited
- Removing visited check causing infinite loops
Solution
Step 1: Understand BFS with cycles
In graphs with cycles, BFS can revisit nodes infinitely unless visited nodes are tracked.Step 2: Modify BFS to track visited and count levels
Use a visited set to avoid revisiting nodes and maintain a level count to find shortest path length. Stop BFS when target node is reached.Final Answer:
Use a visited set to track visited nodes and stop when target is found, counting levels -> Option DQuick Check:
Visited set + level count = shortest path BFS [OK]
- Using DFS which doesn't guarantee shortest path
- Trying to remove cycles manually before BFS
- Using stack which causes DFS behavior
Ready to prove it?
Pass the test and this pattern moves unknown
