Problem Statement
Given a matrix of size M x N, where ‘1’ represents land, while ‘0’ represents water. The task is to return the number of islands present in the matrix. An island is a group of 1’s surrounded either vertically or horizontally.
Examples:
Input:
Output: 3
Explanation: Shown in the image
Approach 1: DFS
The idea is to consider the given matrix as a graph, where each cell is a node of the given graph. Two nodes contain an edge if and only if there is a ‘1’ either horizontally or vertically.
Algorithm
- Scan the matrix from (0,0) to (N, M).
- If the current element is ‘1’, start a DFS.
- In the DFS traversal, mark every visited node.
- Count the number of islands as the number of nodes that trigger the DFS.
- Return count.
C++ Code Implementation
void dfs(vector < vector < char >> & grid, int r, int c) {
int nr = grid.size();
int nc = grid[0].size();
grid[r][c] = '0';
if (r - 1 >= 0 && grid[r - 1][c] == '1') dfs(grid, r - 1, c);
if (r + 1 < nr && grid[r + 1][c] == '1') dfs(grid, r + 1, c);
if (c - 1 >= 0 && grid[r][c - 1] == '1') dfs(grid, r, c - 1);
if (c + 1 < nc && grid[r][c + 1] == '1') dfs(grid, r, c + 1);
}
int numIslands(vector < vector < char >> & grid) {
int nr = grid.size();
if (!nr) return 0;
int nc = grid[0].size();
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
dfs(grid, r, c);
}
}
}
return num_islands;
}
Java Code Implementation
void dfs(char[][] grid, int r, int c) {
int nr = grid.length;
int nc = grid[0].length;
if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {
return;
}
grid[r][c] = '0';
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
dfs(grid, r, c);
}
}
}
return num_islands;
}
Python Code Implementation
def numIslands(self, grid):
if not grid:
return 0
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == "1":
self.dfs(grid, i, j)
count += 1
return count
def dfs(self, grid, i, j):
if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != "1":
return
grid[i][j] = "#"
self.dfs(grid, i + 1, j)
self.dfs(grid, i - 1, j)
self.dfs(grid, i, j + 1)
self.dfs(grid, i, j - 1)
- Time Complexity: O(M * N), where M and N are the size of the matrix
- Space Complexity: O(M * N).
Approach 2: BFS
The problem can also be solved using the BFS approach. The logic remains the same as the previous approach.
Algorithm
- Scan the matrix from (0,0) till (N, M).
- If the current element is ‘1’, start a BFS.
- Consider a queue and put the current node into the queue.
- Iteratively visit its neighbours vertically and horizontally and mark them as visited.
- The count is the total number of times the BFS has been invoked.
- Return count.
C++ Code Implementation
int numIslands(vector < vector < char >> & grid) {
int nr = grid.size();
if (!nr) return 0;
int nc = grid[0].size();
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
grid[r][c] = '0'; // mark as visited
queue < pair < int, int >> neighbors;
neighbors.push({
r,
c
});
while (!neighbors.empty()) {
auto rc = neighbors.front();
neighbors.pop();
int row = rc.first, col = rc.second;
if (row - 1 >= 0 && grid == '1') {
neighbors.push({
row - 1,
col
});
grid = '0';
}
if (row + 1 < nr && grid == '1') {
neighbors.push({
row + 1,
col
});
grid = '0';
}
if (col - 1 >= 0 && grid == '1') {
neighbors.push({
row,
col - 1
});
grid = '0';
}
if (col + 1 < nc && grid == '1') {
neighbors.push({
row,
col + 1
});
grid = '0';
}
}
}
}
}
return num_islands;
Java Code Implementation
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length;
int nc = grid[0].length;
int num_islands = 0;
for (int r = 0; r < nr; ++r) {
for (int c = 0; c < nc; ++c) {
if (grid[r][c] == '1') {
++num_islands;
grid[r][c] = '0'; // mark as visited
Queue < Integer > neighbors = new LinkedList < > ();
neighbors.add(r * nc + c);
while (!neighbors.isEmpty()) {
int id = neighbors.remove();
int row = id / nc;
int col = id % nc;
if (row - 1 >= 0 && grid == '1') {
neighbors.add((row - 1) * nc + col);
grid = '0';
}
if (row + 1 < nr && grid == '1') {
neighbors.add((row + 1) * nc + col);
grid = '0';
}
if (col - 1 >= 0 && grid == '1') {
neighbors.add(row * nc + col - 1);
grid = '0';
}
if (col + 1 < nc && grid == '1') {
neighbors.add(row * nc + col + 1);
grid = '0';
}
}
}
}
}
return num_islands;
}
Python Code Implementation
from collections import deque
def numIslands(grid):
if not grid:
return 0
lands = set(
[
(i, j)
for j in xrange(len(grid[0]))
for i in xrange(len(grid))
if grid[i][j] == "1"
]
)
count = 0
while lands:
count += 1
i, j = lands.pop()
connected = deque()
connected.append((i, j))
while connected:
i, j = connected.popleft()
if (i + 1, j) in lands:
connected.append((i + 1, j))
lands.remove((i + 1, j))
if (i - 1, j) in lands:
connected.append((i - 1, j))
lands.remove((i - 1, j))
if (i, j + 1) in lands:
connected.append((i, j + 1))
lands.remove((i, j + 1))
if (i, j - 1) in lands:
connected.append((i, j - 1))
lands.remove((i, j - 1))
return count
Time Complexity:O(M * N), where M and N is the size of the matrix
Space Complexity:O(min(M,N)).
Practice Question
FAQs
Q.1: What is the time and space complexity of the DFS approach?
Ans: The time and space complexity of the DFS approach is O(M * N) and O(M * N).
Q.2: In terms of space complexity, is the BFS approach efficient over DFS?
Ans: Yes, the space complexity for the BFS approach is O(min(N,M)), in the worst case when the grid is filled completely with 1’s, whereas for DFS it is O(N*M).
