DFS学习笔记
题目
给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。
输入描述:
第一行包含两个整数 N, M,表示矩阵的行数和列数。
后续 N 行,每行包含 M 个数字,数字为 1 或者 0。
输出描述:
输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。
输入示例:
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例:
3
提示信息
根据测试案例中所展示,岛屿数量共有 3 个,所以输出 3。
数据范围:
1 <= N, M <= 50
思路
本题dfs的思路是遍历整个矩阵,把没有遍历过的陆地都标记计数,然后继续搜索与它相连的陆地,并都标为已经遍历。dfs递归调用,参数为矩阵,Boolean类型表示是否访问过,以及正在标记的点的横坐标和纵坐标。
JAVA
代码如下:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
public class daoyushuliang {
static int [][]dir = {{1,0},{-1,0},{0,1},{0,-1}};
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int M = sc.nextInt();//列数
int N = sc.nextInt();//行数
List<List<Integer>> grid = new ArrayList<>();//初始化一个list存储地图信息
for(int i = 0; i< N; i++) {
List<Integer> row = new ArrayList<>();
for(int j = 0; j<M; j++) {
row.add(sc.nextInt());
}
grid.add(row);
}
List<List<Boolean>> visited = new ArrayList<>();//记录访问状态
for(int i = 0; i< N; i++) {
List<Boolean> row = new ArrayList<>();
for(int j = 0; j<M; j++) {
row.add(false);//初始时全部格子标记未访问
}
visited.add(row);
}
int result = 0;//计数
for(int i = 0;i<N; i++) {
for(int j = 0; j<M; j++) {
if(!visited.get(i).get(j)&&grid.get(i).get(j) == 1) {
//如果当前节点标记为未访问并且为陆地
result++;
dfs(grid,visited,i,j);//使用dfs将与当前陆地相连的所有的陆地标记为访问
}
}
}
System.out.println(result);
}
public static void dfs(List<List<Integer>> grid, List<List<Boolean>> visited, int x, int y) {
if(visited.get(x).get(y)||grid.get(x).get(y) == 0) {
return;
}
visited.get(x).set(y, true);
for(int i = 0; i <4; i++) {
int nextx = x+dir[i][0];
int nexty = y+dir[i][1];
if(nextx < 0|| nextx >= grid.size() || nexty <0 || nexty >= grid.get(0).size()) {
continue;
}
dfs(grid, visited, nextx, nexty);
}
}
}
总结
重点二维数组的定义一定要搞清楚。