题目链接:leetcode.cn/problems/as…
题目描述:
你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。
请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该距离。如果网格上只有陆地或者海洋,请返回 -1。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
示例 1:
输入:grid = [[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。
示例 2:
输入:grid = [[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋单元格 (2, 2) 和所有陆地单元格之间的距离都达到最大,最大距离为 4。
提示:
n == grid.lengthn == grid[i].length1 <= n <= 100grid[i][j]不是0就是1
解析
❗将BFS全部搞懂,直接看我前面的几个题目分别是图像渲染——迷宫中离入口最近的出口——多源BFS矩阵❗
这题题目阅读理解难度大于题目本身。找到一个海洋区域,这个海洋区域到与它最近的陆地区域的距离是最大的。
再简单一点讲,先假设有一个陆地,多个海洋,找出海洋离陆地最远的那个。只不过现在有多个陆地,也就是单源变成多源了。
题目中的曼哈顿距离其实就是横坐标的差加上纵坐标的差。
这题其实和矩阵只有一点点区别,矩阵要返回的是所有的值,这题返回的是最大值而已。
和矩阵一样,这题我们的思路还是从陆地去找海洋,因为陆地旁边的海洋是第一层,而直接从海洋开始找的话你不知道你处于第几层。
那么从陆地出发的话我们就要先将所有的陆地存起来,那这里就需要重新创建一个规模一样的表。表中的值初始化为-1(与题目中的值无关,方便判断),然后原来的陆地(为1的值)赋值为0,为什么初始化为0,因为后面赋值要用到。
然后拿着这些陆地去遍历,将它周围的第一层的海洋找出来,并赋值为这一层的值加一,这就是赋值为0的原因,如果你还是初始化为1的话,再加一就变成2了。为什么是直接赋值为这一层的值加一呢?不应该是|x0 - x1| + |y0 - y1|吗,我们已经初始化陆地为0了,我们从陆地往外扩第一层的值应该就是陆地的上下左右位置,这个上下左右位置距离中间的距离都是1,所以直接上一层的值也就是0再加1就行,第二层的话就是1 + 1。以此类推。
最后再在循环外定义一个最大值就行。
代码
class Solution {
static int[] dx = {0, 0, 1, -1};
static int[] dy = {1, -1, 0, 0};
public int maxDistance(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
//因为此处是n * n,所以定义一个就行
int n = grid.length;
//定义一个规格相同的数组方便值
int[][] arr = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//先将数组初始化为-1
arr[i][j] = -1;
if (grid[i][j] == 1) {
//将值为1的位置赋值为0
arr[i][j] = 0;
//再将值为1的存到队列中
queue.add(new int[]{i,j});
}
}
}
//判断是否都为海洋或者陆地
if (queue.size() == n * n || queue.isEmpty()) {
return -1;
}
//定义result用于存储最大值
int result = 1;
while (!queue.isEmpty()) {
int[] cur = queue.poll();
int x = cur[0], y = cur[1];
//往外扩
for (int i = 0; i < 4; i++) {
int x1 = x + dx[i], y1 = y + dy[i];
if (x1 < n && x1 >= 0 && y1 < n && y1 >= 0 && arr[x1][y1] == -1) {
//这一层现在还处于x,y也就是我们正在遍历的这一层。下一层其实就是x1,y1
//所以赋值直接就是arr[x1][y1] = arr[x][y] + 1;
arr[x1][y1] = arr[x][y] + 1;
//再将下一层存入到queue中
queue.add(new int[]{x1,y1});
//更新最大值
result = Math.max(result,arr[x1][y1]);
}
}
}
return result;
}
}