1. 问题描述:
你现在手里有一份大小为 N x N 的「地图」(网格) grid,上面的每个「区域」(单元格)都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋区域,这个海洋区域到离它最近的陆地区域的距离是最大的。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个区域之间的距离是 |x0 - x1| + |y0 - y1| 。
如果我们的地图上只有陆地或者海洋,请返回 -1。
示例 1:
输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋区域 (1, 1) 和所有陆地区域之间的距离都达到最大,最大距离为 2。
示例 2:
输入:[[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋区域 (2, 2) 和所有陆地区域之间的距离都达到最大,最大距离为 4。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible
2. 思路分析:
① 一开始的时候看到题目真的是傻了,这是在说啥,英文看不懂就算了,中文又看不懂难受,于是看了一下题解,题目的意思可以转化为在每一块陆地周围都可能存在着最近的海洋,并且求解的是陆地周围的海洋同时扩散之后的最远距离,理解题目的意思之后就非常好办了,这个是典型的bfs的应用,因为这个也是求解出最大的距离,bfs从源点出发,向四个上下左右四个方向进行扩展,最后那个节点肯定是所有最远的海洋之中距离最大的那个
② 怎么样做呢?我们可以将所有的陆地进行入队,对当前的所有陆地进行四个方向的扩展所以会有多个位置的周围扩展,为了防止被重复访问我们需要使用一个二维数组来标记即将到达的节点是否被访问,这个与之前不同的是,这个在一开始的时候就有多个节点入队,多个节点进行扩散,所以当一个节点先到达一个位置的时候另外一个平行的节点是扩展不到这个位置了,因为这个位置已经先被访问了,所以多个陆地入队进行周围扩散加上一个标记数组就可以解决距离陆地最近的海洋中最远的那个距离,所以使用一次bfs即可以解决,最终扩散到的那个节点一定是最远的,我感觉这个需要仔细理解才会好一点
3. 代码如下:
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
public class Solution {
public static class Node{
/*当前的x, y坐标与到达当前坐标的步数*/
private int x;
private int y;
private int step;
public Node(int x, int y, int step) {
this.x = x;
this.y = y;
this.step = step;
}
}
/*访问数组*/
int vis[][];
/*上下左右四个方向*/
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
public int maxDistance(int[][] grid) {
/*先对陆地进行进入队列*/
Queue<Node> queue = new ArrayDeque<>();
int r = grid.length, c = grid[0].length;
vis = new int[r][c];
int hasLand = 0, hasOcean = 0;
for (int i = 0; i < r; ++i){
for (int j = 0; j < c; ++j){
if (grid[i][j] == 1) {
hasLand = 1;
queue.offer(new Node(i, j, 0));
}
}
}
//用来记录当前节点的位置
int x = 0, y = 0, step = 0;
while (!queue.isEmpty()){
Node poll = queue.poll();
x = poll.x;
y = poll.y;
step = poll.step;
for (int i = 0; i < 4; ++i){
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1 >= 0 && x1 < r && y1 >= 0 && y1 < c && grid[x1][y1] != 1 && vis[x1][y1] != 1){
/*未被访问*/
vis[x1][y1] = 1;
queue.offer(new Node(x1, y1, step + 1));
hasOcean = 1;
}
}
}
if (hasLand == 0 || hasOcean == 0) return -1;
return step;
}
}