LeetCode 1162. 地图分析【最短路径、广度优先搜索】

难度: 中等

题目描述

你现在手里有一份大小为 N x N 的『地图』(网格) grid,上面的每个『区域』(单元格)都用 01 标记好了。其中 0 代表海洋,1 代表陆地,你知道距离陆地区域最远的海洋区域是是哪一个吗?请返回该海洋区域到离它最近的陆地区域的距离。
我们这里说的距离是『曼哈顿距离』( Manhattan Distance):(x0, y0)(x1, y1) 这两个区域之间的距离是 |x0 - x1| + |y0 - y1|
如果我们的地图上只有陆地或者海洋,请返回 -1
示例 1:
在这里插入图片描述

输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2

示例 2:
在这里插入图片描述

输入:[[1,0,0],[0,0,0],[0,0,0]]
输出:4

提示:

  1. 1 <= grid.length == grid[0].length <= 100
  2. grid[i][j] 不是 0 就是 1

思路

计算每个海洋到每个陆地的距离需要的时间复杂度是 O ( n 3 ) O(n^3) O(n3),但是超时(看到n <= 100我以为 O ( n 3 ) O(n^3) O(n3)会过……)。可以从每个陆地开始计算出到每个海洋的最短路径,这样做时间复杂度仍然是 O ( n 3 ) O(n^3) O(n3),但是注意到要求的是距离最近的陆地最远的海洋,所以不用将每个陆地到每个海洋的距离都求出来,只要求出每个海洋到最近的陆地的距离,这可以只用一次dijkstra算法解决,但是由于这道题是网格,用BFS就可以求最短路径,且dijkstra算法没有必要,因为距离近的点一定会先被访问到,不需要松弛。

代码

class Solution {
public:
    static constexpr int next[4][2] = {{1,  0}, {-1, 0}, {0,  1}, {0,  -1}};
    int maxDistance(vector<vector<int>> &grid) {
        queue<pair<int, int>> q;
        
        int r = grid.size(), c = grid[0].size();
        vector<vector<int>> visit(r, vector<int>(c));

        for (int i = 0; i < r; ++i)
            for (int j = 0; j < c; ++j)
                if (grid[i][j] == 1) q.emplace(i, j);

        if (q.empty() || q.size() == r * c) return -1;

        int step = 0;
        while (!q.empty()) {
            ++step;
            int level = q.size();
            for (int i = 0; i < level; ++i) {
                auto front = q.front();
                q.pop();
                for (auto &direct : next) {
                    int nx = front.first + direct[0], ny = front.second + direct[1];
                    if (nx >= 0 && nx < r && ny >= 0 && ny < c && grid[nx][ny] == 0 && !visit[nx][ny]){
                        q.emplace(nx, ny);
                        visit[nx][ny] = true;
                    }
                }
            }
        }

        return step - 1;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值