Island Problems
A collection of classic grid/matrix traversal problems using DFS/BFS. These problems share a common pattern of exploring connected components in a 2D grid.
[!TIP] Common Pattern: Most island problems use the same DFS/BFS templateβiterate through cells, and when you find an unvisited land cell, explore all connected land cells.
Number of Islandsβ
LeetCode 200 | Difficulty: Mediumβ
Problem Descriptionβ
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 lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Constraintsβ
m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]is'0'or'1'
Exampleβ
Input: grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
Output: 3
Visual Representation:
βββββ¬ββββ¬ββββ¬ββββ¬ββββ
β 1 β 1 β 0 β 0 β 0 β β Island 1
βββββΌββββΌββββΌββββΌββββ€
β 1 β 1 β 0 β 0 β 0 β
βββββΌββββΌββββΌββββΌββββ€
β 0 β 0 β 1 β 0 β 0 β β Island 2
βββββΌββββΌββββΌββββΌββββ€
β 0 β 0 β 0 β 1 β 1 β β Island 3
βββββ΄ββββ΄ββββ΄ββββ΄ββββ
Complexityβ
- Time: $O(M \times N)$ β Each cell visited at most once
- Space: $O(M \times N)$ β Visited array + recursion stack (worst case)
Solutionβ
public int NumIslands(char[][] grid)
{
int m = grid.Length, n = grid[0].Length;
bool[,] visited = new bool[m, n];
int count = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i][j] == '1' && !visited[i, j])
{
DFS(grid, visited, i, j);
count++; // Found a new island
}
}
}
return count;
}
void DFS(char[][] grid, bool[,] visited, int i, int j)
{
// Boundary check + water check + visited check
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[0].Length
|| visited[i, j] || grid[i][j] == '0')
return;
visited[i, j] = true;
// Explore all 4 directions
DFS(grid, visited, i - 1, j); // up
DFS(grid, visited, i + 1, j); // down
DFS(grid, visited, i, j - 1); // left
DFS(grid, visited, i, j + 1); // right
}
Max Area of Islandβ
LeetCode 695 | Difficulty: Mediumβ
Problem Descriptionβ
You are given an m x n binary matrix grid. An island is a group of 1s connected 4-directionally. Return the maximum area of an island in grid. If there is no island, return 0.
Constraintsβ
m == grid.lengthn == grid[i].length1 <= m, n <= 50grid[i][j]is0or1
Exampleβ
Input: grid = [
[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]
]
Output: 6
Explanation: The largest island has area 6 (the connected 1s on the right side).
Complexityβ
- Time: $O(M \times N)$
- Space: $O(M \times N)$
Solutionβ
public int MaxAreaOfIsland(int[][] grid)
{
int m = grid.Length, n = grid[0].Length;
bool[,] visited = new bool[m, n];
int maxArea = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i][j] == 1 && !visited[i, j])
{
maxArea = Math.Max(maxArea, DFS(grid, visited, i, j));
}
}
}
return maxArea;
}
int DFS(int[][] grid, bool[,] visited, int i, int j)
{
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[0].Length
|| grid[i][j] == 0 || visited[i, j])
return 0;
visited[i, j] = true;
int area = 1; // Count current cell
area += DFS(grid, visited, i - 1, j);
area += DFS(grid, visited, i + 1, j);
area += DFS(grid, visited, i, j - 1);
area += DFS(grid, visited, i, j + 1);
return area;
}
Island Perimeterβ
LeetCode 463 | Difficulty: Easyβ
Problem Descriptionβ
You are given a row x col grid where grid[i][j] = 1 represents land and grid[i][j] = 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island.
Return the perimeter of the island.
Constraintsβ
row == grid.lengthcol == grid[i].length1 <= row, col <= 100grid[i][j]is0or1- There is exactly one island
Exampleβ
Input: grid = [
[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]
]
Output: 16
Visual Explanation:
Each land cell contributes 4 edges initially.
Subtract 1 for each adjacent land cell.
βββββ
β 1 β β 3 edges (top, left, right)
βββββΌββββΌββββ
β 1 β 1 β 1 β β outer edges only
βββββΌββββΌββββ
β 1 β
βββββΌββββ€
β 1 β 1 β
βββββ΄ββββ
Complexityβ
- Time: $O(M \times N)$
- Space: $O(1)$
Solutionβ
public int IslandPerimeter(int[][] grid)
{
int m = grid.Length, n = grid[0].Length;
int perimeter = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i][j] == 1)
{
// Check all 4 neighbors - add 1 for each water/boundary
int left = (i > 0) ? grid[i - 1][j] : 0;
int right = (i < m - 1) ? grid[i + 1][j] : 0;
int up = (j > 0) ? grid[i][j - 1] : 0;
int down = (j < n - 1) ? grid[i][j + 1] : 0;
perimeter += (left == 0 ? 1 : 0) +
(right == 0 ? 1 : 0) +
(up == 0 ? 1 : 0) +
(down == 0 ? 1 : 0);
}
}
}
return perimeter;
}
Number of Closed Islandsβ
LeetCode 1254 | Difficulty: Mediumβ
Problem Descriptionβ
Given a 2D grid consisting of 0s (land) and 1s (water), an island is a maximal 4-directionally connected group of 0s. A closed island is an island totally surrounded by 1s (not touching any edge).
Return the number of closed islands.
Constraintsβ
1 <= grid.length, grid[0].length <= 1000 <= grid[i][j] <= 1
Exampleβ
Input: grid = [
[1,1,1,1,1,1,1,0],
[1,0,0,0,0,1,1,0],
[1,0,1,0,1,1,1,0],
[1,0,0,0,0,1,0,1],
[1,1,1,1,1,1,1,0]
]
Output: 2
Complexityβ
- Time: $O(M \times N)$
- Space: $O(M \times N)$
Solutionβ
public int ClosedIsland(int[][] grid)
{
int m = grid.Length, n = grid[0].Length;
bool[,] visited = new bool[m, n];
int count = 0;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
if (grid[i][j] == 0 && !visited[i, j])
{
bool touchesBorder = false;
DFS(grid, visited, i, j, ref touchesBorder);
if (!touchesBorder) count++;
}
}
}
return count;
}
void DFS(int[][] grid, bool[,] visited, int i, int j, ref bool touchesBorder)
{
if (i < 0 || i >= grid.Length || j < 0 || j >= grid[0].Length
|| visited[i, j] || grid[i][j] == 1)
return;
// Check if this cell is on the border
touchesBorder = touchesBorder ||
(i == 0 || i == grid.Length - 1 || j == 0 || j == grid[0].Length - 1);
visited[i, j] = true;
DFS(grid, visited, i - 1, j, ref touchesBorder);
DFS(grid, visited, i + 1, j, ref touchesBorder);
DFS(grid, visited, i, j - 1, ref touchesBorder);
DFS(grid, visited, i, j + 1, ref touchesBorder);
}
Number of Islands IIβ
LeetCode 305 | Difficulty: Hard πβ
Problem Descriptionβ
You are given an empty 2D binary grid of size m x n. Initially, all cells are water (0). You may perform addLand operations which turns a water cell into land.
Return an array of integers where answer[i] is the number of islands after the ith operation.
Constraintsβ
1 <= m, n, positions.length <= 10^41 <= m * n <= 10^4positions[i].length == 20 <= ri < m0 <= ci < n
Approachβ
[!IMPORTANT] This problem requires Union-Find for optimal $O(k \cdot \alpha(mn))$ time complexity. Simple DFS would be $O(k \times m \times n)$ which is too slow.
Union-Find Approach:
- Initialize each cell as its own "island" when added
- When adding a new land cell, check all 4 neighbors
- If a neighbor is also land, union them (merge islands)
- Track the count of distinct islands
Solution (Union-Find)β
public IList<int> NumIslands2(int m, int n, int[][] positions)
{
List<int> result = new List<int>();
int[] parent = new int[m * n];
int[] rank = new int[m * n];
Array.Fill(parent, -1); // -1 means water
int count = 0;
int[] dirs = {0, 1, 0, -1, 0};
foreach (var pos in positions)
{
int i = pos[0], j = pos[1];
int id = i * n + j;
if (parent[id] != -1) // Already land (duplicate position)
{
result.Add(count);
continue;
}
parent[id] = id; // New island
count++;
// Check 4 neighbors
for (int d = 0; d < 4; d++)
{
int ni = i + dirs[d], nj = j + dirs[d + 1];
int nid = ni * n + nj;
if (ni >= 0 && ni < m && nj >= 0 && nj < n && parent[nid] != -1)
{
if (Union(parent, rank, id, nid))
count--; // Merged two islands
}
}
result.Add(count);
}
return result;
}
int Find(int[] parent, int x)
{
if (parent[x] != x)
parent[x] = Find(parent, parent[x]); // Path compression
return parent[x];
}
bool Union(int[] parent, int[] rank, int x, int y)
{
int px = Find(parent, x), py = Find(parent, y);
if (px == py) return false; // Already same island
// Union by rank
if (rank[px] < rank[py]) parent[px] = py;
else if (rank[px] > rank[py]) parent[py] = px;
else { parent[py] = px; rank[px]++; }
return true;
}
Interview Tipsβ
- DFS vs BFS: Both work for island problems; DFS is simpler to write, BFS avoids stack overflow on large grids
- Modify grid in-place?: Can mark visited by changing
'1'to'0'to save space, but discuss trade-offs - 8-directional variants: Some problems count diagonal connectionsβadd 4 more directions
- Common follow-ups:
- What if the grid is too large to fit in memory? β Streaming/chunking
- What if we need to support dynamic updates? β Union-Find
Related Problemsβ
- 733. Flood Fill β Same DFS pattern
- 417. Pacific Atlantic Water Flow β Multi-source BFS from edges
- 827. Making A Large Island β Union-Find with virtual node
- 1020. Number of Enclaves β Count cells in closed islands