以前做题都是ac评论区写个答案完事,现在想想还是得做个记录,总结一下都做的题都涉及了哪些知识。
题目
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围
题目链接
这类题也做了不少了,BFS,DFS看完就忘,这次记录(其实就是看别人题解重复注释一遍)下来以后忘了再看。
public class LeetCode200 {
private int row;
private int col;
private boolean[][] visit;
private char[][] Grid;
/**
* 方向数组,代表当前节点的下,上,右,左;此顺序与遍历过程无关
*/
private static int[] x = new int[]{1, -1, 0, 0};
private static int[] y = new int[]{0, 0, 1, -1};
/**
* DFS:从头开始遍历,找到第一个未被访问过的陆地,从该节点开始上下左右扩展,直至访问完所有能通过该陆地到达的陆地
*/
public int numIslands(char[][] grid) {
row = grid.length;
if (row == 0) {
return 0;
}
col = grid[0].length;
Grid = grid;
visit = new boolean[row][col];
int res = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (!visit[i][j] && Grid[i][j] == '1') {
//遇到一个未访问的陆地结果加一
res++;
//访问其周边陆地
dfs(i, j);
}
}
}
return res;
}
private void dfs(int curX, int curY) {
//四个方向
for (int i = 0; i < 4; i++) {
int newX = curX + x[i];
int newY = curY + y[i];
//区域内,未被访问过,且为陆地
if (isArea(newX, newY) && !visit[newX][newY] && Grid[newX][newY] == '1') {
visit[newX][newY] = true;
dfs(newX, newY);
}
}
}
/**
* BFS:遇到一个陆地,入队其四周未被访问的陆地,循环至队列为空,岛屿加一遍历到下一个陆地
*/
public int numIslands2(char[][] grid) {
row = grid.length;
//去除空数组
if (row == 0) {
return 0;
}
col = grid[0].length;
Grid = grid;
visit = new boolean[row][col];
Queue<Integer> queue = new LinkedList<>();
int res = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (!visit[i][j] && Grid[i][j] == '1') {
//使用一个整数存放下标
queue.offer(col * i + j);
while (!queue.isEmpty()) {
int poll = queue.poll();
int curX = poll / col;
int curY = poll % col;
for (int k = 0; k < 4; k++) {
int newX = curX + x[k];
int newY = curY + y[k];
if (isArea(newX, newY) && !visit[newX][newY] && Grid[newX][newY] == '1') {
//遇到周边陆地入队完立即设置访问为true,否则可能会重复入队
queue.offer(col * newX + newY);
visit[newX][newY] = true;
}
}
}
//一个岛屿遍历结束,结果加一
res++;
visit[i][j] = true;
}
}
}
return res;
}
private boolean isArea(int x, int y) {
return x >= 0 && x < row && y >= 0 && y < col;
}
}
DFS:先加岛屿数,遍历完这个岛屿换下一个
BFS:先遍历完岛屿,再加岛屿数换下一个
不过LeetCode dfs比bfs快好多,不知道少了dfs回溯却更慢是为啥