今天是2020年4月20日,星期一。
题目描述
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。
题目分析
可以看出这个问题是一个典型的BFS问题。在BFS问题中,我们通常借助队列+标识数组来完成广度优先遍历。推荐去看一下weiwei大佬的题解,出门右转:岛屿数量。
在遍历数组的过程中,每次向其余四个方向进行寻找,如果已经访问过该元素,或者该元素不为’1’,则不处理;否则一定满足该元素未被访问过 && 该元素未'1'
,此时岛屿数量需要加1,并搜索该元素的四周。
该题目还可以使用深度优先遍历DFS来解决。在向一个方向搜索时,不断搜索,直到搜索到某一个元素的值不为’1’。在weiwei大佬的题解中有动态图示来进行展示,这里就不在赘述。
参考代码
- BFS参考代码
public int numIslands(char[][] grid) {
int rows = grid.length;
int cols = grid[0].length;
if (rows <= 0) {
return 0;
}
// 记录是否某个元素已经访问过了
boolean[][] flag = new boolean[rows][cols];
// 记录岛屿的个数
int count = 0;
int[] distanceX = {1, -1, 0, 0};
int[] distanceY = {0, 0, 1, -1};
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (!flag[row][col] && grid[row][col] == '1') {
count++;
// 用于记录周围的是否被访问过的1,如果是1的话则加入队列中
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{row, col});
while (!queue.isEmpty()) {
int[] point = queue.poll();
for (int i = 0; i < 4; i++) {
int x = point[0] + distanceX[i];
int y = point[1] + distanceY[i];
// 防止下标越界
if (x >= 0 && y >= 0 && x < rows && y < cols && !flag[x][y] && grid[x][y] == '1') {
// 此处需要对当前访问的元素进行标记,防止多次访问同一个元素。并将该元素加入到队列中。
flag[x][y] = true;
queue.offer(new int[]{x, y});
}
}
}
}
}
}
return count;
}
- DFS参考代码
/**
* 题目参考weiwei大佬的dfs完成
*
* @param grid
* @return
*/
public int numIslands(char[][] grid) {
int rows = grid.length;
if (rows <= 0) {
return 0;
}
int cols = grid[0].length;
boolean[][] flag = new boolean[rows][cols];
int count = 0;
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (!flag[row][col] && grid[row][col] == '1') {
// 此时应该去dfs
count++;
dfs(row, col, flag, rows, cols, grid);
}
}
}
return count;
}
private void dfs(int x, int y, boolean[][] flag, int rows, int cols, char[][] grid) {
int[] distanceX = {1, -1, 0, 0};
int[] distanceY = {0, 0, 1, -1};
flag[x][y] = true;
for (int i = 0; i < 4; i++) {
int pointX = distanceX[i] + x;
int pointY = distanceY[i] + y;
if (inArea(pointX, pointY, rows, cols) && !flag[pointX][pointY] && grid[pointX][pointY] == '1') {
dfs(pointX, pointY, flag, rows, cols, grid);
}
}
}
private boolean inArea(int x, int y, int rows, int cols) {
return x >= 0 && x < rows && y >= 0 && y < cols;
}