LeetCode: 200. Number of Islands
LeetCode: 200. Number of Islands
Summary
Given an m x n 2D binary grid grid, which represents a map of '1's (land) and '0's (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent land cells horizontally or vertically. You may assume that all four edges of the grid are surrounded by water.
Approach
We use the Union-Find data structure to track connected components of land cells.
Each land cell "1" is treated as an independent island at the beginning.
We do not need to count water cells because the maximum possible number of islands is the number of "1" cells.
We iterate through the grid and union adjacent land cells. If two land cells are connected, they belong to the same island, so the total island count decreases by one.
To simplify the implementation, we map each 2D coordinate (i, j) to a 1D index.
id = i * cols + j
This allows us to use a standard Union-Find structure with 1D arrays.
For each land cell, we only check the right and bottom neighbors. This avoids duplicate checks because the left and top neighbors will already have been processed.
Whenever two adjacent land cells are unioned successfully, the island count is decremented.
Union-Find optimizations:
- Path compression in
find - Union by size to keep tree shallow.
Time complexity is nearly linear:
O(M*N*alpha(M*N))
Where alpha is the inverse Ackermann function, which grows extremely slowly and can be tread as constant in practice.
Here, alpha is the inverse Ackermann function, which grows extremely slowly and can be treated as a constant in practice.
Function
Initialization:
- rows, cols: Grid dimensions
- parent: array of size rows*cols
- size: array of size rows*cols
- count: number of land cells
Function find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
Function union(x, y):
root_x = find(x)
root_y = find(y)
if root_x == root_y: return 0 if size[root_x] < size[root_y]: parent[root_x] = root_y size[root_y] += size[root_x] else: parent[root_y] = root_x size[root_x] += size[root_y] return 1
Main logic: rows = len(grid) cols = len(grid[0])
parent = [i for i in range(rowscols)] size = [1] * (rowscols)
count initial land cells
for i in 0..rows-1: for j in 0..cols-1: if grid[i][j] == "1": count += 1
for i in 0..rows-1: for j in 0..cols-1: if grid[i][j] == "0": continue current = i * cols + j for (ni, nj) in [(i+1, j), (i, j+1)]: if ni < rows and nj < cols and grid[ni][nj] == "1": neighbor = ni*cols+nj count -= union(current, neighbor) return count
Complexity
Time Complexity: O(M*N*alpha(M*N))
Space Complexity: O(M*N)