Connected Components Using BFS in DSA Go - Time & Space Complexity
We want to understand how long it takes to find all connected parts in a graph using BFS.
How does the time needed grow as the graph gets bigger?
Analyze the time complexity of the following code snippet.
func connectedComponents(graph map[int][]int) int {
visited := make(map[int]bool)
count := 0
for node := range graph {
if !visited[node] {
bfs(node, graph, visited)
count++
}
}
return count
}
func bfs(start int, graph map[int][]int, visited map[int]bool) {
queue := []int{start}
visited[start] = true
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
for _, neighbor := range graph[current] {
if !visited[neighbor] {
visited[neighbor] = true
queue = append(queue, neighbor)
}
}
}
}
This code counts how many connected groups are in a graph by visiting each node once using BFS.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node and its neighbors once in BFS.
- How many times: Each node and edge is checked exactly once during the BFS traversals.
As the graph grows, the time grows with the number of nodes and edges.
| Input Size (n nodes, e edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 25 visits (nodes + edges) |
| 100 nodes, 200 edges | About 300 visits |
| 1000 nodes, 5000 edges | About 6000 visits |
Pattern observation: The work grows roughly in a straight line with the total nodes plus edges.
Time Complexity: O(n + e)
This means the time grows linearly with the number of nodes plus edges in the graph.
[X] Wrong: "BFS takes O(n²) time because it uses nested loops."
[OK] Correct: BFS visits each node and edge only once, so it does not repeat work for every pair of nodes.
Understanding BFS time complexity helps you explain graph traversal efficiency clearly and confidently in interviews.
"What if the graph was represented as an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
Step 1: Understand BFS role in connected components
BFS explores all nodes reachable from a given start node, grouping them as one connected component.Step 2: Differentiate BFS from other graph properties
BFS does not directly find shortest paths between arbitrary nodes, max degree, or edge count in this context.Final Answer:
All nodes reachable from a starting node forming one connected component -> Option DQuick Check:
BFS finds connected components [OK]
- Confusing BFS with shortest path only
- Thinking BFS counts edges or degrees
- Mixing connected components with graph size
Solution
Step 1: Identify correct queue data structure for BFS
BFS requires a queue to hold nodes; a slice of ints is a common and correct choice in Go.Step 2: Eliminate incorrect queue initializations
Maps, integers, or strings cannot function as queues for BFS traversal.Final Answer:
queue := []int{} // empty slice for BFS queue -> Option AQuick Check:
Queue for BFS = slice of ints [OK]
- Using map instead of slice for queue
- Using integer or string as queue
- Not initializing queue before BFS
graph := map[int][]int{
0: {1},
1: {0, 2},
2: {1},
3: {4},
4: {3},
5: {},
}
visited := make(map[int]bool)
count := 0
for node := range graph {
if !visited[node] {
queue := []int{node}
visited[node] = true
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
for _, neighbor := range graph[current] {
if !visited[neighbor] {
visited[neighbor] = true
queue = append(queue, neighbor)
}
}
}
count++
}
}
fmt.Println(count)Solution
Step 1: Identify connected components in the graph
Nodes 0,1,2 form one component; nodes 3,4 form second; node 5 alone forms third.Step 2: BFS visits each component once, incrementing count
Loop visits nodes 0,3,5 as unvisited starts, counting 3 components total.Final Answer:
3 -> Option AQuick Check:
3 connected components = 3 [OK]
- Counting edges instead of components
- Missing isolated nodes as components
- Not marking visited nodes properly
func countComponents(graph map[int][]int) int {
visited := make(map[int]bool)
count := 0
for node := range graph {
if visited[node] {
queue := []int{node}
visited[node] = true
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
for _, neighbor := range graph[current] {
if !visited[neighbor] {
visited[neighbor] = true
queue = append(queue, neighbor)
}
}
}
count++
}
}
return count
}Solution
Step 1: Analyze the if condition for BFS start
The code starts BFS only if visited[node] is true, which is wrong; it should start if node is not visited.Step 2: Understand impact on BFS traversal
Because of wrong condition, BFS never starts, so count remains zero incorrectly.Final Answer:
The condition should be if !visited[node], not if visited[node] -> Option CQuick Check:
Start BFS on unvisited nodes [OK]
- Using visited[node] instead of !visited[node]
- Not initializing visited map
- Forgetting to increment count
Solution
Step 1: Recognize isolated nodes must be in graph map
To count isolated nodes as components, they must appear in the graph with empty adjacency lists.Step 2: Include node 7 with empty neighbors before BFS
Adding node 7 ensures BFS visits it as a separate component.Final Answer:
Include node 7 in the graph map with empty adjacency list before BFS -> Option BQuick Check:
Isolated nodes need empty adjacency list [OK]
- Ignoring isolated nodes not in adjacency list
- Assuming isolated nodes are counted automatically
- Connecting isolated nodes incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
