200. 岛屿数量(BFS | DFS)
题目:200. 岛屿数量
public class NumIslands_200 {
public static void main(String[] args) {
char[][] grid = {
{ '1', '1', '1', '1', '0' },
{ '1', '1', '0', '1', '0' },
{ '1', '1', '0', '0', '0' },
{ '0', '0', '0', '0', '0' }};
System.out.println(numIslands(grid));
}
/** 网格 */
private static char[][] grid;
/** 网格行数 */
private static int row;
/** 网格列数 */
private static int col;
/** 标记数组:标记格子是否访问过 */
private static boolean[][] marked;
/** 方向数组:上下左右 */
private static final int[][] directions = {
{ -1, 0 },
{ 0, 1 },
{ 1, 0 },
{ 0, -1 }};
/** 队列 */
private static LinkedList<Integer> queue = new LinkedList<>();
/**
* 获取岛屿的数量
* @param grid 网格
* @return 网格中岛屿的数量
*/
public static int numIslands(char[][] grid) {
row = grid.length;
// 如果数组为空,直接返回
if (row == 0) {
return 0;
}
col = grid[0].length;
// 使用成员变量,避免来回传递数组
NumIslands_200.grid = grid;
// 初始化访问标记数组
marked = new boolean[row][col];
// 岛屿数量
int res = 0;
// 遍历网格数组
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
// 未被访问,并且是陆地的时候
if (!marked[i][j] && grid[i][j] == '1') {
// 广度优先搜索
// bfs(i, j);
// 深度优先搜索
dfs(i, j);
res++;
}
}
}
return res;
}
/**
* 广度优先搜索
* @param i 网格的行坐标
* @param j 网格的列坐标
*/
public static void bfs(int i, int j) {
// 先置为访问
marked[i][j] = true;
// 坐标转换成值入队列
queue.addLast(i * col + j);
while (!queue.isEmpty()) {
// 头节点出队
int head = queue.removeFirst();
// 还原坐标
int headX = head / col;
int headY = head % col;
// 探索四个方向是否是陆地
for (int k = 0; k < 4; k++) {
int newX = headX + directions[k][0];
int newY = headY + directions[k][1];
// 未越界,未被访问,并且是陆地的时候
if (isInArea(newX, newY) && !marked[newX][newY] && grid[newX][newY] == '1') {
// 节点入队列
queue.addLast(newX * col + newY);
// 当前节点置为访问
marked[newX][newY] = true;
}
}
}
}
/**
* 深度优先搜索
* @param i 网格的行坐标
* @param j 网格的列坐标
*/
private static void dfs(int i, int j) {
marked[i][j] = true;
// 探索四个方向是否是陆地
for (int k = 0; k < 4; k++) {
int newX = i + directions[k][0];
int newY = j + directions[k][1];
// 未越界,未被访问,并且是陆地的时候
if (isInArea(newX, newY) && !marked[newX][newY] && grid[newX][newY] == '1') {
// 递归遍历
dfs(newX, newY);
}
}
}
/**
* 判断坐标 (x, y) 是否在网格内
* @param x 行坐标
* @param y 列坐标
* @return true 在网格内
*/
public static boolean isInArea(int x, int y) {
return 0 <= x && x < row && 0 <= y && y < col;
}
}