大家好,都吃晚饭了吗?我是Kaiqisan,是一个已经走出社恐的一般生徒,今天爷又回来了,继续昨天的并查集,来结合例题讲讲深搜的奇妙用法
问题
如图,求岛的数量
{0, 0, 1, 0, 1, 0}
{1, 1, 1, 0, 1, 0}
{1, 0, 0, 1, 0, 0}
{0, 0, 0, 0, 0, 0}
图中 0 代表海洋,1代表陆地(PS:陆地直接无法通过斜对角的陆地来直接连接)
所以图中一共有3块陆地
思路
先进行遍历,对所有的数组成员进行遍历,如果碰到一块陆地就使用递归进行深搜,在深搜的时候如果碰到旁边是陆地的话就进行标记,在后面的遍历以及深搜的过程中都会被忽视
就以上面的那个二位数组为例
{0, 0, 1, 0, 1, 0}
{1, 1, 1, 0, 1, 0}
{1, 0, 0, 1, 0, 0}
{0, 0, 0, 0, 0, 0}
我们开始像读书一样,从左往右从上往下遍历,我们首先看到了第一行第三个元素为1,所以,我们从这里开始深搜,并做标记(把所有遍历到符合条件的元素),深搜完成,岛的总数+1
{0, 0, 2, 0, 1, 0}
{2, 2, 2, 0, 1, 0}
{2, 0, 0, 1, 0, 0}
{0, 0, 0, 0, 0, 0}
第二次找到陆地
{0, 0, 2, 0, 2, 0}
{2, 2, 2, 0, 2, 0}
{2, 0, 0, 1, 0, 0}
{0, 0, 0, 0, 0, 0}
…以此类推
就这样我们完成所有的遍历之后,返回累计发现的岛的数量
代码
static int doFind(int[][] island) {
int res = 0;
for (int i = 0; i < island.length; i++) {
for (int j = 0; j < island[0].length; j++) {
if (island[i][j] == 1) {
res++;
doInfect(island, i, j);
}
}
}
return res;
}
static void doInfect(int[][] island, int i, int j) {
int hei = island.length;
int wid = island[0].length;
// 不符合条件的全部驳回(越界,重复遍历,找到海洋)
if (i < 0 || i >= hei || j < 0 || j >= wid || island[i][j] != 1) {
return;
}
island[i][j] = 2;
doInfect(island, i + 1, j);
doInfect(island, i - 1, j);
doInfect(island, i, j + 1);
doInfect(island, i, j - 1);
}
总结
没有总结,建议在合适的地方使用深搜,在数据量大的时候还是很耗内存的(今天写力扣使用深搜就直接内存爆炸了)