1043-矩阵中的距离

题目如下

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:
在这里插入图片描述
输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

示例 2:
在这里插入图片描述
输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]

解题思路

广度优先搜索
矩阵可以看作是无权图,该问题与图的最近距离有关,因此可以考虑使用广度优先搜索解决。广度优先搜索需要使用一个队列,因为题目中需要求每个格子距离 0 的最短距离,可以考虑把所有为 0 的格子作为初始节点添加到队列中,然后以这些点为起点开始广度搜索。

另外需要一个 dists 矩阵保存各个格子距离最近的 0 的距离,如果 mat[i][j] 等于 0 则初始化为 0,因为该距离最近的 0 的距离自然是 0,如果 mat[i][j] 等于 0 则初始化为 INT_MAX。

每次都从队列中取出坐标为 pos 的格子,取该格子距离最近的 0 的距离 dist 为 dists[i][j],设该格子往上下左右方向到达的格子为 [r, c] 。若格子 [r, c] 之前从未被搜索过,那么 dists[i][j] 为 INT_MAX,则 dist + 1 < dists[i][j] 必成立,并且该格子距离 0 的最近距离为 dist + 1,即更新 dists[i][j] 为 dist + 1。

如果之前已经搜索过格子 [r, c],则 dist + 1 不会小于 dists[i][j]。因为广度优先已经保证之前搜索到该格子时为最小距离。可以这样理解,因为队列的初始节点为格子为 0 的节点,若这些节点在出列时该格子周围没有 1 格子,则其四周的格子不会加入队列,故由初始节点出列而加入队列的第一批格子就是距离 0 的最近距离为 1 的格子,那么由第一批格子出队列而加入队列的第二批格子就是距离 0 的最近距离为 2 的格子。依次类推,所以后加入的格子确定的距离不可能小于之前的。

完整代码如下,若输入的矩阵的行列为 m 和 n,则节点数为 O(mn),边数也为 O(mn),所以时间复杂度为 O(mn),空间复杂度为 O(mn)。

class Solution
{
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) 
    {
        vector<vector<int>> dists(mat.size(), vector<int>(mat[0].size()));
        queue<pair<int, int>> que;
        vector<vector<int>> dirs{ {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
        for (int i = 0; i < mat.size(); ++i)
        {
            for (int j = 0; j < mat[0].size(); ++j)
            {
                if (mat[i][j] == 0) 
                {
                    dists[i][j] = 0;
                    que.push({ i, j });
                }
                else 
                {
                    dists[i][j] = INT_MAX;
                }
            }
        }

        while (!que.empty()) 
        {
            auto pos = que.front();
            que.pop();
            int dist = dists[pos.first][pos.second];

            for (auto& d : dirs)
            {
                int r = pos.first + d[0];
                int c = pos.second + d[1];
                if (r >= 0 && r < mat.size() && c >= 0 && c < mat[0].size())
                {
                    if (dist + 1 < dists[r][c])
                    {
                        dists[r][c] = dist + 1;
                        que.push({ r, c });
                    }
                }
            }
        }
        return dists;
    }
};

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值