题目
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
思路
只需要遍历数组,一旦发现有陆地并且没有被访问过,就开始进行深搜,还要判断整个过程中是否有出现岛屿的陆地与边界接壤的情况。有就不能增加岛屿数目。
代码
class Solution {
static int ans;//岛屿数目
static int visited[][]=new int[110][110];
static int n;//地图行数
static int m;//地图列数
static boolean is_border=false;//没有靠近边界
//方向数组
static int d_x[]={0,1,0,-1};
static int d_y[]={1,0,-1,0};
public int closedIsland(int[][] grid) {
n=grid.length;
m=grid[0].length;
for (int i=0;i<n;++i)
for (int j=0;j<m;++j)
visited[i][j]=0;
ans=0;
for(int i=0;i<n;++i)
for (int j=0;j<m;++j)
{
if (grid[i][j]==0 && visited[i][j]==0)//找到陆地,并且陆地没有被访问
{
dfs(i,j,grid);
if (is_border==true) //判断深搜过程是否有接近边界的陆地
is_border=false;
else
++ans;
}
}
return ans;
}
private void dfs(int x, int y,int grid[][]) {
//深搜每个点,先检查这个点是否接近边界
if (checkIsBorder(x,y))
is_border=true;
//将该陆地标记为已经访问
visited[x][y]=1;
int t_x=0;
int t_y=0;
for (int g=0;g<=3;++g)
{
t_x=x+d_x[g];
t_y=y+d_y[g];
if (check(t_x,t_y,grid)) //是陆地
{
visited[t_x][t_y]=1;//已经访问,并且不再需要回溯
dfs(t_x,t_y,grid);
}
}
}
//是陆地,没有被访问过,并且没有越界
private boolean check(int x, int y,int [][]grid)
{
return x>=0 && x<n && y>=0 && y<m && visited[x][y]==0 && grid[x][y]==0;
}
//判断是否靠近边界
private boolean checkIsBorder(int a,int b)
{
if (a-1==-1 || a+1==n || b-1==-1 || b+1==m)
return true;
return false;
}
}
结果
AC了,但是,刚刚忘记了,如果使用静态的标记数组的话,需要每次在进行搜索前,都要讲标记数组给初始化为0.不然,有多个测试例子的话,会造成结果的混乱。