Connected Components Using BFS in DSA Javascript - Time & Space Complexity
We want to understand how the time needed to find connected parts in a graph grows as the graph gets bigger.
How does the work change when the number of nodes and edges increases?
Analyze the time complexity of the following code snippet.
function bfs(graph, start, visited) {
const queue = [start];
visited[start] = true;
while (queue.length > 0) {
const node = queue.shift();
for (const neighbor of graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.push(neighbor);
}
}
}
}
function connectedComponents(graph) {
const visited = {};
let count = 0;
for (const node in graph) {
if (!visited[node]) {
bfs(graph, node, visited);
count++;
}
}
return count;
}
This code finds how many connected groups are in a graph using BFS to explore each group.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node and checking its neighbors using BFS.
- How many times: Each node and each edge is visited once during the entire process.
As the graph grows, the time to check all nodes and edges grows roughly in proportion to their total number.
| Input Size (n nodes, m 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 as the sum of nodes and edges, increasing linearly as the graph gets bigger.
Time Complexity: O(n + m)
This means the time needed grows linearly with the number of nodes plus the number of edges in the graph.
[X] Wrong: "The BFS runs in O(n²) because it has nested loops."
[OK] Correct: Although BFS uses loops inside loops, each edge and node is visited only once, so the total work is linear, not quadratic.
Understanding this time complexity helps you explain how graph traversal scales and shows you can analyze real-world problems involving networks or connections.
"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 purpose in connected components
BFS explores all nodes reachable from a starting node, marking them as part of the same connected component.Step 2: Differentiate BFS from other graph properties
BFS does not directly find shortest paths between arbitrary nodes, maximum degree, or edge count in this context.Final Answer:
All nodes reachable from a starting node forming one connected component -> Option AQuick Check:
BFS finds connected components = D [OK]
- Confusing BFS with shortest path only
- Thinking BFS counts edges or degrees
- Mixing BFS with DFS concepts
Solution
Step 1: Identify correct queue initialization
In JavaScript, a queue for BFS is commonly implemented using an array with push() to add elements.Step 2: Check other options for errors
Set does not have push(), object {} has no enqueue method, and null cannot be used as a queue.Final Answer:
const queue = []; queue.push(startNode); -> Option BQuick Check:
Array with push() for queue = B [OK]
- Using Set instead of array for queue
- Using object without queue methods
- Initializing queue as null
const graph = {
0: [1],
1: [0, 2],
2: [1],
3: [4],
4: [3]
};
function bfs(start, visited) {
const queue = [start];
visited[start] = true;
const component = [];
while (queue.length) {
const node = queue.shift();
component.push(node);
for (const neighbor of graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.push(neighbor);
}
}
}
return component;
}
const visited = {};
const components = [];
for (const node in graph) {
if (!visited[node]) {
components.push(bfs(node, visited));
}
}
console.log(components);Solution
Step 1: Trace BFS from node 0
BFS visits 0, then 1, then 2 forming component [0,1,2].Step 2: Trace BFS from node 3
Next unvisited node is 3, BFS visits 3 and 4 forming component [3,4].Final Answer:
[[0,1,2],[3,4]] -> Option AQuick Check:
Two connected components found = A [OK]
- Assuming all nodes in one component
- Mixing order of nodes in components
- Ignoring visited tracking
function bfs(start, visited, graph) {
const queue = [start];
visited[start] = true;
const component = [];
while (queue.length > 0) {
const node = queue.pop();
component.push(node);
for (const neighbor of graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
queue.push(neighbor);
}
}
}
return component;
}Solution
Step 1: Check queue operation for BFS
BFS requires removing from front (queue.shift()), but code uses pop() which removes from end, making it DFS behavior.Step 2: Verify other parts
Start node is marked visited, for loop syntax is correct, and push() is correct to add neighbors at end.Final Answer:
Using queue.pop() instead of queue.shift() causes wrong BFS order -> Option CQuick Check:
pop() breaks BFS order = A [OK]
- Confusing pop() with shift() in queue
- Not marking visited nodes
- Incorrect loop syntax
Solution
Step 1: Understand BFS role in counting components
Each BFS call from an unvisited node explores one connected component fully.Step 2: Modify BFS to count components
Instead of storing nodes, just increment a counter when BFS starts from an unvisited node.Final Answer:
Increment a counter each time BFS starts from an unvisited node, without collecting nodes -> Option DQuick Check:
Count BFS starts = connected components [OK]
- Storing all nodes unnecessarily
- Confusing edge count with component count
- Switching BFS to DFS without reason
Ready to prove it?
Pass the test and this pattern moves unknown
