题目描述
你现在手里有一份大小为 N x N 的『地图』(网格) grid,上面的每个『区域』(单元格)都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,你知道距离陆地区域最远的海洋区域是是哪一个吗?请返回该海洋区域到离它最近的陆地区域的距离。
我们这里说的距离是『曼哈顿距离』( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个区域之间的距离是 |x0 - x1| + |y0 - y1| 。
如果我们的地图上只有陆地或者海洋,请返回 -1。
思路分析
BFS
树的BFS就是层序遍历,图的BFS区别在
- 源点可能多个,先把多个源点入队;
- 无向图必须标志访问,用memo或者直接原地修改数组。
本题就是多源点的BFS,把所有的陆地看成一个整体,从各个陆地开始同时向外一层一层的扩散,最后扩散到的海洋就是最远的海洋。
其实多源点BFS可以看成是单源点BFS的第二层。有一个超级源点连接着多源点,我们用队列实现。
代码实现
public int maxDistance(int[][] grid) {
int[] dx={0,0,1,-1};
int[] dy={1,-1,0,0};
Queue<int[]> queue=new ArrayDeque<>();
int n=grid.length;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
queue.offer(new int[]{i,j});
}
}
}
boolean hasOcean=false;
int[] point =null;
while(!queue.isEmpty()){
point=queue.poll();
int x= point[0];
int y= point[1];
for(int i=0;i<4;i++){
int newX=x+dx[i];
int newY=y+dy[i];
if(newX<0||newX>=n||newY<0||newY>=n||grid[newX][newY]!=0){
continue;
}
grid[newX][newY]=grid[x][y]+1;
hasOcean=true;
queue.offer(new int[]{newX,newY});
}
}
if(point == null || !hasOcean){
return -1;
}
return grid[point[0]][point[1]]-1;
}