Title:
Given a two-dimensional grid consisting of'1'(land) and'0' (water), the number of islands is calculated. An island is surrounded by water and connected by adjacent land in either horizontal or vertical directions. You can assume that all four sides of the grid are surrounded by water.
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: 11110 11010 11000 00000 Output: 1
Example 2:
Input: 11000 11000 00100 00011 Output: 3
Ideas for solving problems:
First understand the definition of an island: a piece of 1 surrounded by all 0, that is, an island. (Note: 1 and 0 in the grid array are char characters, not integers)
In Example 1, all 1 can be connected together, that is, all 1 forms an island. The three islands in Example 2: four islands in the upper left corner, one in the middle and one in the lower right corner constitute three islands respectively.
Flood fill algorithm is a classical algorithm that extracts several connected points from a region and distinguishes them from other adjacent regions (or dyes them differently). It is named for its idea that floods spread from one area to all the areas that can be reached. In GNU Go and mine clearance, the Flood Fill algorithm is used to calculate the area to be cleared. As can be seen from the above definition, this problem is a typical example of Flood fill algorithm type, which separates the island from water and dyes it in a specific color to record the accumulated island.
Each island can be regarded as a connected node. If all the connected nodes are traversed thoroughly and marked with special values to record that the node has visited, an island can be proved to have been found at the end of traversal.
Three methods of solving problems:
- DFS (Depth First Search): Visit from a 1-based root node, from each adjacent 1 node down to the vertex (surrounded by water), and then to the other adjacent 1 node to the vertex.
- BFS (breadth-first search): Starting from a root node of 1, accessing one node downward each time until the last vertex is accessed
-
And Search: Also known as Joint Search Data Structure, because it is mainly realized by Joint Search and Find processes:
- Find: Determine which subset of elements belong to. It can be used to determine whether two elements belong to the same subset.
- Union: Two subsets are merged into one set.
In order to solve this problem, a root node 1 is used as the initial node to determine whether the surrounding node is 1, and if so, a new set is built and the node is used as the parent node. Then traverse the next node, if it is 1, find the parent node of the node (that is, the first node), and point all the parent nodes of the node around the node 1 to the parent node of the node, and so on, until all the 1 nodes of the island join the same set. The number of final collections (the number of parent nodes) is the number of islands.
DFS:
Time complexity: O(M * N), where M and N are rows and columns, respectively.
Spatial complexity: The worst case is O(M * N), when the whole grid is land, the depth of depth-first search reaches M * N.
Java:
class Solution { public int numIslands(char[][] grid) { if (grid == null || grid.length == 0) return 0; int row = grid.length, columns = grid[0].length, count = 0; for (int i = 0; i < row; i++) {//Traverse all points for (int j = 0; j < columns; j++) { if (grid[i][j] == '1') { dfs(grid, i, j, row, columns);//dfs traverses all connected points count++;//Recording the number of islands } } } return count; } private void dfs(char[][] grid, int i, int j, int row, int columns) { if (i < 0 || j < 0 || i >= row || j >= columns || grid[i][j] == '0') return;//Baseline conditions grid[i][j] = '0';//Traversed point set 0 dfs(grid, i + 1, j, row, columns); dfs(grid, i, j + 1, row, columns); dfs(grid, i - 1, j, row, columns); dfs(grid, i, j - 1, row, columns); } }
Python:
class Solution: def numIslands(self, grid: List[List[str]]) -> int: if not grid or len(grid) == 'o': return 0 row, columns = len(grid), len(grid[0]) count = 0 for i in range(row): for j in range(columns): if grid[i][j] == '1': self.dfs(grid, i, j, row, columns) count += 1 return count def dfs(self, grid: List[List[str]], i: int, j: int, row: int, columns: int): if i >= row or i < 0 or j >= columns or j < 0 or grid[i][j] == '0': return grid[i][j] = '0' self.dfs(grid, i - 1, j, row, columns) self.dfs(grid, i, j - 1, row, columns) self.dfs(grid, i + 1, j, row, columns) self.dfs(grid, i, j + 1, row, columns)
BFS:
Time complexity: O(M * N), where M and N are rows and columns, respectively.
Spatial complexity: O (min(M, N), in the worst case (all land), the queue size can reach min(M, N).
Java:
class Solution { public int numIslands(char[][] grid) { if (grid == null || grid.length == 0) return 0; int row = grid.length, columns = grid[0].length, count = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < columns; j++) {//Traverse all nodes if (grid[i][j] == '1') { bfs(grid, i, j, row, columns); count++;//Recording the number of islands } } } return count; } private void bfs(char[][] grid, int i, int j, int row, int columns) { Queue<Integer> loc = new LinkedList<>();//Points with a queue temporary value of 1 loc.add(i * columns + j);//The location of this point can also be represented by an array of [i,j], but it takes up twice as much space. while (!loc.isEmpty()) { int id = loc.remove();//Remove position int r = id / columns, c = id % columns;//Decomposition to index if (r - 1 >= 0 && grid[r - 1][c] == '1') { loc.add((r - 1) * columns + c); grid[r - 1][c] = '0'; } if (r + 1 < row && grid[r + 1][c] == '1') { loc.add((r + 1) * columns + c); grid[r + 1][c] = '0'; } if (c - 1 >= 0 && grid[r][c - 1] == '1') { loc.add(r * columns + c - 1); grid[r][c - 1] = '0'; } if (c + 1 < columns && grid[r][c + 1] == '1') { loc.add(r * columns + c + 1); grid[r][c + 1] = '0'; } } } }
Python3:
class Solution: def numIslands(self, grid: List[List[str]]) -> int: if not grid or len(grid) == 'o': return 0 row, columns = len(grid), len(grid[0]) count = 0 for i in range(row): for j in range(columns): if grid[i][j] == '1': self.bfs(grid, i, j, row, columns) count += 1 return count def bfs(self, grid: List[List[str]], i: int, j: int, row: int, columns: int): queue = collections.deque() queue.append((i, j)) # Locations are queued in tuples while queue: r, c = queue.popleft() if r + 1 < row and grid[r + 1][c] == '1': queue.append((r + 1, c)) grid[r + 1][c] = '0' if r - 1 >= 0 and grid[r - 1][c] == '1': queue.append((r - 1, c)) grid[r - 1][c] = '0' if c + 1 < columns and grid[r][c + 1] == '1': queue.append((r, c + 1)) grid[r][c + 1] = '0' if c - 1 >= 0 and grid[r][c - 1] == '1': queue.append((r, c - 1)) grid[r][c - 1] = '0'
And collect:
This solution is cumbersome and inefficient. The following java codes are referenced from LeetCode. A simple understanding of his ideas can expand his thinking:
Java:
class Solution { class UnionFind { int count; //count int[] parent; int[] rank; public UnionFind(char[][] grid) { count = 0; int m = grid.length, n = grid[0].length; parent = new int[m * n]; rank = new int[m * n]; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (grid[i][j] == '1') { parent[i * n + j] = i * n + j; ++count; } rank[i * n + j] = 0; } } } public int find(int i) { if (parent[i] != i) parent[i] = find(parent[i]); return parent[i]; } public void union(int x, int y) { int rootx = find(x); int rooty = find(y); if (rootx != rooty) { if (rank[rootx] > rank[rooty]) { parent[rooty] = rootx; } else if (rank[rootx] < rank[rooty]) { parent[rootx] = rooty; } else { parent[rooty] = rootx; rank[rootx] += 1; } --count; } } public int getCount() { return count; } } public int numIslands(char[][] grid) { if (grid == null || grid.length == 0) return 0; int row = grid.length, columns = grid[0].length; UnionFind uf = new UnionFind(grid); for (int i = 0; i < row; ++i) { for (int j = 0; j < columns; ++j) { if (grid[i][j] == '1') { grid[i][j] = '0'; if (i - 1 >= 0 && grid[i - 1][j] == '1') uf.union(i * columns + j, (i - 1) * columns + j); if (i + 1 < row && grid[i + 1][j] == '1') uf.union(i * columns + j, (i + 1) * columns + j); if (j - 1 >= 0 && grid[i][j - 1] == '1') uf.union(i * columns + j, i * columns + j - 1); if (j + 1 < columns && grid[i][j + 1] == '1') uf.union(i * columns + j, i * columns + j + 1); } } } return uf.getCount(); } }
Welcome to pay attention to Weixingong. All the people come together to refuel acridine: love to write Bug