题目描述 :
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
解题思路:深搜,广搜,并查集
解法一:深搜
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int ans = 0;
int m = grid.length, n = grid[0].length;
for (int i = 0; i < m ; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '1') {
ans++;
dfs(grid, i , j);
}
}
}
return ans;
}
private void dfs(char[][] grid, int i, int j) {
int m = grid.length, n = grid[0].length;
if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] == '0') {
return;
}
grid[i][j] = '0';
dfs(grid, i - 1, j);
dfs(grid, i, j - 1);
dfs(grid, i + 1, j);
dfs(grid, i, j + 1);
}
}
解法二:广搜
class Solution {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0 ;
}
int nr = grid.length, nc = grid[0].length;
int ans = 0;
for (int r = 0; r < nr; r++) {
for (int c = 0; c < nc; c++) {
if (grid[r][c] == '1') {
ans++;
grid[r][c] = '0';
Deque<Integer> neighbors = new LinkedList<>();
neighbors.offer(r * nc + c);
while (!neighbors.isEmpty()) {
int id = neighbors.poll();
int row = id /nc, col = id % nc;
if (row - 1 >= 0 && grid[row - 1][col] == '1') {
neighbors.offer((row - 1) * nc + col);
grid[row - 1][col] = '0';
}
if (row + 1 < nr && grid[row + 1][col] == '1') {
neighbors.offer((row + 1) * nc + col);
grid[row + 1][col] = '0';
}
if (col - 1 >= 0 && grid[row][col - 1] == '1') {
neighbors.offer(row * nc + col - 1);
grid[row][col - 1] = '0';
}
if (col + 1 < nc && grid[row][col + 1] == '1') {
neighbors.offer(row * nc + col + 1);
grid[row][col + 1] = '0';
}
}
}
}
}
return ans;
}
}
解法三:并查集
class Solution {
// 并查集
class UnionFind {
int 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), rootY = find(y);
if (rootY != rootX) {
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 nr = grid.length, nc = grid[0].length;
UnionFind uf = new UnionFind(grid);
for (int r = 0; r < nr; r++) {
for (int c = 0; c < nc; c++) {
if (grid[r][c] == '1') {
grid[r][c] = '0';
if (r - 1 >= 0 && grid[r-1][c] == '1') {
uf.union(r * nc + c, (r-1)*nc + c);
}
if (r + 1 < nr && grid[r+1][c] == '1') {
uf.union(r * nc + c, (r+1) * nc + c);
}
if (c - 1 >= 0 && grid[r][c-1] == '1') {
uf.union(r * nc + c, r * nc + c - 1);
}
if (c + 1 < nc && grid[r][c+1] == '1') {
uf.union(r * nc + c, r * nc + c + 1);
}
}
}
}
return uf.getCount();
}
}