昨晚听左神讲了一个很有意思的题。题目意思大概是:
给定一个二维数组,所有位置的值不是0就是1。规定每个位置可以和它上下左右位置上的值相连。有一个叫做岛的概念,定义如下:
连成一片的1,如果周围都是0,那么这一片1,构成一个岛。
求整张图上有多少个岛。
例如:
0 0 0 0 0 0 0 0 0
0 1 1 0 0 1 1 1 0
0 1 1 1 0 0 0 1 0
0 1 1 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0
0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0
这张图上有三个岛。
0 0 0 0 0 0 0 0 0
0 1 1 0 1 1 1 1 0
0 1 1 1 1 0 0 1 0
0 1 1 0 0 0 0 1 0
0 0 0 0 0 1 1 1 0
0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 0
这张图上有一个岛。
遇到这种题目,我的第一反应就是针对二维数组中的元素进行逐次用BFS或DFS进行遍历,如果遇到边界或值为0的时候,就停下来,统计BFS或DFS的遍历次数即可
然而左神给了与BFS差不多的思路,然而在整体实现上比BFS简单的多
比如说,如果登岛的时候(当第一次遇见值为1的时候),就对周边的1进行感染,那么这个岛就会被一次感染完。如果遇到其他岛屿的话,如上操作。那么我们可以根据几次感染的次数对岛屿的个数进行估计
void infect(int *arr, int i, int j, int w, int h) {
if (i < 0 || i >= h || j < 0 || j >= w || arr[i*w + j] != 1)
return;
arr[i*w+j] = 2;
infect(arr, i - 1, j, w, h);
infect(arr, i + 1, j, w, h);
infect(arr, i, j - 1, w, h);
infect(arr, i, j + 1, w, h);
}
int calcIsland(int *arr, int w, int h) {
int res = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (arr[i*w + j] == 1) {
res++;
infect(arr, i, j, w, h);
}
}
}
return res;
}