题目
给出一个二维数组 A,每个单元格为 0(代表海)或 1(代表陆地)。
移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。
返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
思路
如果想直接找出周围被水包围着的陆地数目可能需要比较负责的判断条件,可以逆向思维。找出那些跟边界相连的陆地,用总的陆地数目减去那些跟边界相连的陆地,这就可以了!
用一个广搜就行了!
代码
import java.util.*;
/*
* 0 代表海 1 代表陆地
* */
class Element
{
int x;
int y;
public Element(int x, int y)
{
this.x = x;
this.y = y;
}
}
class Solution {
int ans=0; //陆地总数
int row=0; //地图行数
int column=0; //地图列数
int map[][] = new int[512][512]; //复制的地图
int visited[][]= new int[512][512]; //标记数组
int direction[][]={{0,1},{1,0},{0,-1},{-1,0}}; //方向数组
Deque<Element> deque = new LinkedList<>(); //搜索队列
public int numEnclaves(int[][] grid)
{
row=grid.length;
column= grid[0].length;
deque.clear();
for (int i=0;i<row;++i)
{
for (int j=0;j<column;++j)
{
map[i][j]=grid[i][j]; //复制地图
visited[i][j]=0; //标记数组
if (grid[i][j]==1)
++ans;
}
}
for (int i=0;i<row;++i)
{
// 找出第一列的陆地
if (map[i][0]==1 && visited[i][0]==0)
{
visited[i][0]=1;
deque.add(new Element(i,0));
bfs();
}
// 找出最后一列的陆地
if (map[i][column-1]==1 && visited[i][column-1]==0)
{
visited[i][column-1]=1;
deque.add(new Element(i,column-1));
bfs();
}
}
for (int j=0;j<column;++j)
{
// 找出第一行的陆地
if (map[0][j]==1 && visited[0][j]==0)
{
visited[0][j]=1;
deque.add(new Element(0,j));
bfs();
}
// 找出最后一行的陆地
if (map[row-1][j]==1 && visited[row-1][j]==0)
{
visited[row-1][j]=1;
deque.add(new Element(row-1,j));
bfs();
}
}
return ans;
}
private void bfs()
{
while (!deque.isEmpty())
{
--ans;
Element temp = deque.poll();
int t_x=0;
int t_y=0;
// 往四个方向搜索
for (int i=0;i<4;++i)
{
t_x = temp.x+direction[i][0];
t_y = temp.y+direction[i][1];
if (check(t_x,t_y))
{
visited[t_x][t_y]=1;
deque.add(new Element(t_x,t_y));
}
}
}
}
private boolean check(int x, int y)
{
// 行坐标不越界 列坐标不越界 当前地图是陆地 没有被访问过
return x>=0 && x<row && y>=0 && y<column && map[x][y]==1 && visited[x][y]==0;
}
}
结果
有点慢!