101 Logo
onenoughtone

Connected Components Pattern

What are Connected Components?

In an undirected graph, a connected component is a subgraph in which any two vertices are connected to each other by paths, and which is connected to no additional vertices in the graph.

In simpler terms, a connected component is a group of vertices that are all reachable from each other.

Problem Statement

Given an undirected graph, find all connected components in the graph.

Example:

Graph: A -- B -- C
        D -- E -- F
        G

Connected components: [A, B, C], [D, E, F], [G]

BFS Approach

  1. Initialize a set to keep track of visited vertices and an array to store all connected components
  2. For each unvisited vertex in the graph:
    • Run BFS starting from this vertex to find all vertices in its connected component
    • Add the component to the list of components
  3. Return the list of all connected components

Implementation

Here's an implementation of the connected components algorithm using BFS:

function findConnectedComponents(graph) { // Set to keep track of visited vertices const visited = new Set(); // Array to store all connected components const components = []; // For each vertex in the graph for (const vertex in graph) { // If this vertex has not been visited yet if (!visited.has(vertex)) { // Find all vertices in the same component as this vertex const component = bfsComponent(graph, vertex, visited); // Add this component to the list of components components.push(component); } } return components; } function bfsComponent(graph, startVertex, visited) { // Queue for BFS const queue = [startVertex]; // Mark the start vertex as visited visited.add(startVertex); // Array to store vertices in this component const component = [startVertex]; // While there are vertices in the queue while (queue.length > 0) { // Dequeue a vertex from the queue const currentVertex = queue.shift(); // Get all adjacent vertices of the dequeued vertex for (const neighbor of graph[currentVertex]) { // If this adjacent vertex has not been visited if (!visited.has(neighbor)) { // Mark it as visited and enqueue it visited.add(neighbor); queue.push(neighbor); // Add it to this component component.push(neighbor); } } } return component; } // Example usage: const graph = { 'A': ['B'], 'B': ['A', 'C'], 'C': ['B'], 'D': ['E'], 'E': ['D', 'F'], 'F': ['E'], 'G': [] }; const components = findConnectedComponents(graph); console.log(components); // Output: [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]

Time and Space Complexity

Time Complexity:

O(V + E), where V is the number of vertices and E is the number of edges in the graph.

Space Complexity:

O(V), where V is the number of vertices in the graph.

Related Problem: Number of Islands

A classic application of the connected components pattern is the Number of Islands problem, where we need to count the number of islands in a 2D grid.

function numIslands(grid) { if (!grid || grid.length === 0) { return 0; } const rows = grid.length; const cols = grid[0].length; let count = 0; // Directions: up, right, down, left const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; // Function to check if a cell is valid and is land function isValid(row, col) { return row >= 0 && row < rows && col >= 0 && col < cols && grid[row][col] === '1'; } // BFS to mark all connected land cells as visited function bfs(row, col) { const queue = [[row, col]]; grid[row][col] = '0'; // Mark as visited by changing '1' to '0' while (queue.length > 0) { const [currentRow, currentCol] = queue.shift(); // Check all four directions for (const [dr, dc] of directions) { const newRow = currentRow + dr; const newCol = currentCol + dc; if (isValid(newRow, newCol)) { queue.push([newRow, newCol]); grid[newRow][newCol] = '0'; // Mark as visited } } } } // Iterate through each cell in the grid for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { // If we find a land cell, start BFS and increment count if (grid[i][j] === '1') { count++; bfs(i, j); } } } return count; } // Example usage: const grid = [ ['1', '1', '0', '0', '0'], ['1', '1', '0', '0', '0'], ['0', '0', '1', '0', '0'], ['0', '0', '0', '1', '1'] ]; const islands = numIslands(grid); console.log(islands); // Output: 3
IntroVisualizePatternsPractice
101 Logo
onenoughtone