Given a 2d grid map of '1's (land) and '0's (water), count 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.
Example 1:
Input: 1 1 1 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 Output: 1
Example 2:
Input: 1 1 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 Output: 3
The core challenge of this problem is to identify and count distinct islands in a 2D grid. An island is defined as a group of horizontally or vertically connected '1's (land) surrounded by '0's (water). This problem is significant in various applications such as geographical mapping, image processing, and network connectivity.
Potential pitfalls include not correctly identifying connected components or missing edge cases where islands are at the boundaries of the grid.
To solve this problem, we can use Depth-First Search (DFS) or Breadth-First Search (BFS) to traverse the grid and mark visited lands. Here’s a step-by-step approach:
A naive solution would involve checking each cell and performing a search for connected lands. However, this approach can be inefficient due to repeated searches.
An optimized solution involves using DFS or BFS to traverse and mark all connected lands starting from each unvisited land cell. This ensures each cell is processed only once.
1. Iterate through each cell in the grid. 2. When a '1' is found, initiate a DFS to mark all connected '1's. 3. Increment the island count for each DFS initiation.
Here’s a detailed breakdown of the DFS algorithm:
/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function(grid) {
if (!grid || grid.length === 0) return 0;
let numIslands = 0;
// Helper function to perform DFS
const dfs = (grid, i, j) => {
// Check for out of bounds or water
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] === '0') {
return;
}
// Mark the cell as visited by setting it to '0'
grid[i][j] = '0';
// Perform DFS in all four directions
dfs(grid, i + 1, j); // down
dfs(grid, i - 1, j); // up
dfs(grid, i, j + 1); // right
dfs(grid, i, j - 1); // left
};
// Iterate through each cell in the grid
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] === '1') {
numIslands++;
dfs(grid, i, j);
}
}
}
return numIslands;
};
The time complexity of this approach is O(M*N), where M is the number of rows and N is the number of columns. This is because each cell is visited once. The space complexity is O(M*N) in the worst case due to the recursion stack in DFS.
Potential edge cases include:
Testing these edge cases ensures the robustness of the solution.
To test the solution comprehensively, consider the following test cases:
Using a testing framework like Jest can help automate and validate these test cases.
When approaching such problems, consider the following tips:
Understanding and solving the "Number of Islands" problem is crucial for mastering grid-based traversal algorithms. By practicing and exploring different approaches, you can enhance your problem-solving skills and prepare for more complex challenges.
For further reading and practice, consider the following resources: