DFS学习笔记

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);
		}
	}

}


总结

重点二维数组的定义一定要搞清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值