Number of Connected Components in an Undirected Graph Solution
Number of Connected Components in an Undirected Graph solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript.
Number of Connected Components in an Undirected Graph is a medium coding problem on depth-first search, breadth-first search and graph, asked in Amazon, Google, Meta and Twitter interviews.
- Difficulty: Medium
- Topics: Depth-First Search, Breadth-First Search, Graph, Union Find
- Asked at: Amazon, Google, Meta, Twitter
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
You are given n nodes labelled 0 through n - 1 and a list of undirected edges, where edges[i] = [a, b] joins nodes a and b.
Return the number of connected components in the graph.
Example 1
Input: n = 5, edges = [[0,1],[1,2],[3,4]]
Output: 2
Example 2
Input: n = 5, edges = [[0,1],[1,2],[2,3],[3,4]]
Output: 1
Example 3
Input: n = 3, edges = []
Output: 3
Constraints
1 <= n <= 400 <= edges.length <= 60There are no duplicate edges and no self-loops.
Hints for Number of Connected Components in an Undirected Graph
Hint 1
Start from
ncomponents and merge as you process edges.Hint 2
Union-find with path compression makes each merge nearly constant time.
Hint 3
Every edge that joins two different roots reduces the component count by one.
How to solve Number of Connected Components in an Undirected Graph
Start with n singleton components and union along every edge; each edge that joins two different roots merges two components.
Approach
- Initialise
parent[i] = iandcomponents = n. - For each edge, find both roots; if they differ, link them and decrement
components. - Return
components.
Why it works
Union-find maintains the partition of nodes into connected sets exactly; an edge inside an existing set changes nothing, an edge across sets merges them. Path compression keeps each find near-constant.
Complexity
- Time —
O((n + e) · α(n)) - Space —
O(n)
Pitfalls
- A DFS/BFS counting how many times a fresh start is needed works equally well.
Reference solution
Python
def countComponents(n: int, edges) -> int:
parent = list(range(n))
def find(x):
while parent[x] != x:
parent[x] = parent[parent[x]]
x = parent[x]
return x
components = n
for a, b in edges:
ra, rb = find(a), find(b)
if ra != rb:
parent[ra] = rb
components -= 1
return componentsJava
public static int countComponents(int n, int[][] edges) {
int[] parent = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
int components = n;
for (int[] e : edges) {
int a = findRoot(parent, e[0]);
int b = findRoot(parent, e[1]);
if (a != b) {
parent[a] = b;
components--;
}
}
return components;
}
private static int findRoot(int[] parent, int x) {
while (parent[x] != x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}C++
static int findRoot(vector<int>& parent, int x) {
while (parent[x] != x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
int countComponents(int n, vector<vector<int>>& edges) {
vector<int> parent(n);
for (int i = 0; i < n; i++) parent[i] = i;
int components = n;
for (const auto& e : edges) {
int a = findRoot(parent, e[0]);
int b = findRoot(parent, e[1]);
if (a != b) {
parent[a] = b;
components--;
}
}
return components;
}JavaScript
var countComponents = function(n, edges) {
const parent = [];
for (let i = 0; i < n; i++) parent.push(i);
const find = function(x) {
while (parent[x] !== x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
};
let components = n;
for (let i = 0; i < edges.length; i++) {
const a = find(edges[i][0]);
const b = find(edges[i][1]);
if (a !== b) {
parent[a] = b;
components--;
}
}
return components;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 201 depth-first search problems · the whole catalogue
Learn the technique: Depth-First Search (DFS) · Breadth-First Search (BFS)