Leetcode每日一题(1162. 地图分析)

1162. 地图分析

题目

你现在手里有一份大小为 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1.分析
  • 题目问的是「距离陆地区域最远的海洋区域」,其实就是从陆地(1)开始,要扩散多少次,才能把所有的海洋给覆盖掉。「最远」应该从这个角度来理解。
  • 而「该海洋区域到离它最近的陆地区域的距离」,「最近」是因为一定是距离这个最后才扩散到的海洋的最近的陆地才能扩散到它。
2.设计
  • 二维表格上的问题,常用的算法是深度优先遍历、广度优先遍历和并查集,由于这里计算的结果和距离相关,显然使用广度优先遍历;

  • 但是题目问的是「距离陆地区域最远的海洋区域」,这和我们的经验稍微有点出入。一般而言,「广度优先遍历」求的是最短路径,但仔细一想,发现其实广度优先遍历也是适用的:

    求最短路径的时候,只要找到目标值,返回即可;
    求最长路径的时候,所有目标值都看完以后,才返回。

  • 这道题「广度优先遍历」的起点有多个,但完全不影响算法的正确性,可以假想一个虚拟的起点,初始的起点就是由虚拟起点扩散开来的,

3.实现
package com.sq;

import java.util.ArrayDeque;
import java.util.Queue;

/**
 * @Author: iamasd
 * @Description:
 * @Date: Created in 17:382020/3/29
 */
public class Test13 {
    public static void main(String[] args) {
        int[][] grid = {{1,0,1},{0,0,0},{1,0,1}};
        int i = maxDistance(grid);
        System.out.println(i);
    }

    public static int maxDistance(int[][] grid) {
        int[] dx = {0, 0, 1, -1};
        int[] dy = {1, -1, 0, 0};

        Queue<int[]> queue = new ArrayDeque<>();
        int m = grid.length, n = grid[0].length;
        // 先把所有的陆地都入队。
        for (int i = 0; i < m; 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], y = point[1];
            // 取出队列的元素,将其四周的海洋入队。
            for (int i = 0; i < 4; i++) {
                int newX = x + dx[i];
                int newY = y + dy[i];
                if (newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0) {
                    continue;
                }
                grid[newX][newY] = grid[x][y] + 1; // 这里我直接修改了原数组,因此就不需要额外的数组来标志是否访问
                hasOcean = true;
                queue.offer(new int[] {newX, newY});
            }
        }

        // 没有陆地或者没有海洋,返回-1。
        if (point == null || !hasOcean) {
            return -1;
        }

        // 返回最后一次遍历到的海洋的距离。
        return grid[point[0]][point[1]] - 1;
    }
}

4.总结

1.BFS-DFS可参考
2.针对这种二维问题,考虑构建方向向量。

发布了9 篇原创文章 · 获赞 3 · 访问量 438

猜你喜欢

转载自blog.csdn.net/qq_41740808/article/details/105189254
今日推荐