You have a graph of n nodes. You are given an integer n and an array edges where edges[i] = [ai, bi] indicates that there is an edge between ai and bi in the graph.
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
Constraints:
1 <= n <= 20001 <= edges.length <= 5000edges[i].length == 20 <= ai <= bi < nai != biProblem Overview: You are given n nodes labeled from 0 to n-1 and a list of undirected edges. The task is to determine how many connected components exist in the graph. A connected component is a group of nodes where every node is reachable from any other node in that group.
Approach 1: Graph Traversal using DFS/BFS (O(n + m) time, O(n + m) space)
Build an adjacency list from the edge list, then traverse the graph. Iterate through every node. If a node has not been visited, start a traversal (either Depth-First Search or Breadth-First Search) from that node and mark all reachable nodes as visited. Each time you start a new traversal, you have discovered a new connected component. The adjacency list takes O(n + m) space where m is the number of edges. The traversal visits each node and edge once, giving O(n + m) time complexity. This approach works well when you already represent the graph explicitly and want a clear traversal-based solution.
Approach 2: Union-Find / Disjoint Set (O(n + m · α(n)) time, O(n) space)
The Union-Find data structure groups nodes into sets representing components. Initially, every node is its own parent. For each edge (u, v), perform a union(u, v) operation to merge their sets. Use path compression and union by rank to keep the structure shallow. After processing all edges, the number of distinct roots equals the number of connected components. The amortized cost of each operation is nearly constant, α(n) (inverse Ackermann function). This approach avoids building adjacency lists and is particularly efficient when edges arrive incrementally or when solving multiple connectivity queries.
Both strategies rely on the same insight: nodes belong to the same component if there exists a path between them in the graph. Traversal explicitly explores that path structure, while Union-Find tracks connectivity through set merges.
Recommended for interviews: DFS or BFS traversal is the most commonly expected solution because it demonstrates understanding of graph representation and traversal. Union-Find is also highly valued since it shows familiarity with a powerful connectivity data structure. A candidate who can explain both approaches and their tradeoffs shows strong graph fundamentals.
First, we construct an adjacency list g based on the given edges, where g[i] represents all neighbor nodes of node i.
Then we traverse all nodes. For each node, we use DFS to traverse all its adjacent nodes and mark them as visited until all its adjacent nodes have been visited. In this way, we have found a connected component, and the answer is incremented by one. Then we continue to traverse the next unvisited node until all nodes have been visited.
The time complexity is O(n + m), and the space complexity is O(n + m). Where n and m are the number of nodes and edges, respectively.
Python
Java
C++
Go
TypeScript
JavaScript
We can use a union-find set to maintain the connected components in the graph.
First, we initialize a union-find set, then traverse all the edges. For each edge (a, b), we merge nodes a and b into the same connected component. If the merge is successful, it means that nodes a and b were not in the same connected component before, and the number of connected components decreases by one.
Finally, we return the number of connected components.
The time complexity is O(n + m times \alpha(n)), and the space complexity is O(n). Where n and m are the number of nodes and edges, respectively, and \alpha(n) is the inverse of the Ackermann function, which can be regarded as a very small constant.
Python
Java
C++
Go
TypeScript
We can also use BFS (Breadth-First Search) to count the number of connected components in the graph.
Similar to Solution 1, we first construct an adjacency list g based on the given edges. Then we traverse all nodes. For each node, if it has not been visited, we start BFS traversal from this node, marking all its adjacent nodes as visited, until all its adjacent nodes have been visited. In this way, we have found a connected component, and the answer is incremented by one.
After traversing all nodes, we get the number of connected components in the graph.
The time complexity is O(n + m), and the space complexity is O(n + m). Where n and m are the number of nodes and edges, respectively.
Python
Java
C++
Go
TypeScript
| Approach | Complexity |
|---|---|
| DFS | — |
| Union-Find | — |
| BFS | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| DFS/BFS Graph Traversal | O(n + m) | O(n + m) | General graph problems when adjacency lists are easy to build and you want explicit traversal |
| Union-Find (Disjoint Set) | O(n + m · α(n)) | O(n) | Connectivity problems, dynamic edge additions, or when avoiding adjacency lists |
Number of Connected Components in an Undirected Graph - Union Find - Leetcode 323 - Python • NeetCode • 257,758 views views
Watch 9 more video solutions →Practice Number of Connected Components in an Undirected Graph with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor