DFS Component Counting
Intuition
We build an adjacency list and iterate through all nodes. For each unvisited node, we start a DFS to visit all nodes in its connected component and increment a component counter. DFS naturally explores the entire connected component from any starting node by following edges to unvisited neighbors. The number of times we initiate a new DFS equals the number of connected components, since each DFS fully explores one component before we search for the next unvisited node.
Algorithm
- Build an adjacency list from the edges.
- Create a visited set and initialize a component counter to 0.
- Iterate through nodes 0 to n-1. For each unvisited node, increment the counter and run DFS.
- In DFS, mark the current node as visited and recursively visit all unvisited neighbors.
- After all nodes have been processed, return the component counter.
O(V + E) where V is the number of nodes and E is the number of edgesSpaceO(V + E) for the adjacency list and visited setCode (C++ · Java · Python · Go)
class Solution {
public:
int countComponents(int n, vector<vector<int>>& edges) {
vector<vector<int>> graph(n);
for (auto& e : edges) {
graph[e[0]].push_back(e[1]);
graph[e[1]].push_back(e[0]);
}
vector<bool> visited(n, false);
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
count++;
dfs(graph, visited, i);
}
}
return count;
}
private:
void dfs(vector<vector<int>>& graph, vector<bool>& visited, int node) {
visited[node] = true;
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
dfs(graph, visited, neighbor);
}
}
}
};class Solution {
public int countComponents(int n, int[][] edges) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
for (int[] e : edges) {
graph.get(e[0]).add(e[1]);
graph.get(e[1]).add(e[0]);
}
boolean[] visited = new boolean[n];
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
count++;
dfs(graph, visited, i);
}
}
return count;
}
private void dfs(List<List<Integer>> graph, boolean[] visited, int node) {
visited[node] = true;
for (int neighbor : graph.get(node)) {
if (!visited[neighbor]) {
dfs(graph, visited, neighbor);
}
}
}
}from typing import List
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
graph = [[] for _ in range(n)]
for a, b in edges:
graph[a].append(b)
graph[b].append(a)
visited = set()
count = 0
def dfs(node):
visited.add(node)
for neighbor in graph[node]:
if neighbor not in visited:
dfs(neighbor)
for i in range(n):
if i not in visited:
count += 1
dfs(i)
return countfunc countComponents(n int, edges [][]int) int {
graph := make([][]int, n)
for i := range graph {
graph[i] = []int{}
}
for _, e := range edges {
graph[e[0]] = append(graph[e[0]], e[1])
graph[e[1]] = append(graph[e[1]], e[0])
}
visited := make([]bool, n)
count := 0
var dfs func(int)
dfs = func(node int) {
visited[node] = true
for _, neighbor := range graph[node] {
if !visited[neighbor] {
dfs(neighbor)
}
}
}
for i := 0; i < n; i++ {
if !visited[i] {
count++
dfs(i)
}
}
return count
}