Number of Islands
Count 4-connected components of 1s in a binary grid — DFS or Union-Find.
4 min read
union-find dfs grid
Problem#
Given an m x n grid of '0' and '1', count the number of islands — maximal 4-connected components of '1' cells.
Examples#
[["1","1","0"],["1","0","0"],["0","0","1"]]→2.[["1","1","1","1","0"],["1","1","0","1","0"],["1","1","0","0","0"],["0","0","0","0","0"]]→1.
Constraints#
1 <= m, n <= 300.
Hints#
Hint
DFS from each unvisited
'1', marking visited cells; increment the answer per launch. Approach#
Iterate every cell. On finding a '1', increment the count and DFS-flood the connected region, flipping cells to '0' to mark visited.
Solution#
class Solution {public: int numIslands(vector<vector<char>>& grid) { int m = grid.size(), n = grid[0].size(); function<void(int,int)> dfs = [&](int r, int c) { if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] != '1') return; grid[r][c] = '0'; dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1); }; int cnt = 0; for (int r = 0; r < m; ++r) for (int c = 0; c < n; ++c) if (grid[r][c] == '1') { ++cnt; dfs(r, c); } return cnt; }};func numIslands(grid [][]byte) int { m, n := len(grid), len(grid[0]) var dfs func(r, c int) dfs = func(r, c int) { if r < 0 || r >= m || c < 0 || c >= n || grid[r][c] != '1' { return } grid[r][c] = '0' dfs(r+1, c) dfs(r-1, c) dfs(r, c+1) dfs(r, c-1) } cnt := 0 for r := 0; r < m; r++ { for c := 0; c < n; c++ { if grid[r][c] == '1' { cnt++ dfs(r, c) } } } return cnt}class Solution: def numIslands(self, grid: List[List[str]]) -> int: m, n = len(grid), len(grid[0])
def dfs(r: int, c: int) -> None: if r < 0 or r >= m or c < 0 or c >= n or grid[r][c] != '1': return grid[r][c] = '0' dfs(r + 1, c) dfs(r - 1, c) dfs(r, c + 1) dfs(r, c - 1)
cnt = 0 for r in range(m): for c in range(n): if grid[r][c] == '1': cnt += 1 dfs(r, c) return cntfunction numIslands(grid) { const m = grid.length, n = grid[0].length; const dfs = (r, c) => { if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] !== '1') return; grid[r][c] = '0'; dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1); }; let cnt = 0; for (let r = 0; r < m; r++) { for (let c = 0; c < n; c++) { if (grid[r][c] === '1') { cnt++; dfs(r, c); } } } return cnt;}class Solution { private int m, n; private char[][] grid;
public int numIslands(char[][] grid) { this.grid = grid; this.m = grid.length; this.n = grid[0].length; int cnt = 0; for (int r = 0; r < m; r++) { for (int c = 0; c < n; c++) { if (grid[r][c] == '1') { cnt++; dfs(r, c); } } } return cnt; }
private void dfs(int r, int c) { if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] != '1') return; grid[r][c] = '0'; dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1); }}function numIslands(grid: string[][]): number { const m = grid.length, n = grid[0].length; const dfs = (r: number, c: number): void => { if (r < 0 || r >= m || c < 0 || c >= n || grid[r][c] !== '1') return; grid[r][c] = '0'; dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1); }; let cnt = 0; for (let r = 0; r < m; r++) { for (let c = 0; c < n; c++) { if (grid[r][c] === '1') { cnt++; dfs(r, c); } } } return cnt;}Editorial#
Flipping cells to '0' during DFS doubles as a visited mark, eliminating a separate seen matrix. Each cell visited once total, so O(M * N). Union-Find is an equally valid alternative — union neighboring '1' cells, then count roots — useful if dynamic additions are expected.
Complexity#
- Time: O(M * N).
- Space: O(M * N) recursion stack worst case.
Concept revision#
Related#