剑指 Offer II 107. 矩阵中的距离

剑指 Offer II 107. 矩阵中的距离

一、题目

原题链接:Offer II 107. 矩阵中的距离

1.题目描述

给定一个由 01 组成的矩阵 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]]

提示:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 10^4
  • 1 <= m * n <= 10^4
  • mat[i][j] is either 0 or 1.
  • mat 中至少有一个 0

注意:本题与leetcode 542 题相同:01矩阵

2.基础框架

C++基础框架代码如下:

vector<vector<int> > updateMatrix(vector<vector<int> >& mat){
}

3.解题思路

  • 题目分析
  1. 题目目标是返回矩阵,其中每个单元格子中的值为到最近0的距离。
  2. 可以从矩阵中0对应的位置出发,分别对它们进行广度优先遍历周围的位置,从而周围位置得到距离0位置的值。
  3. 为了得到矩阵中所有0的位置,需要遍历一次矩阵mat,并将0的位置以pair类型存入队列q中。
  4. 开始时队列中都是0,分别从0出发,对它们的周围的位置进行扩张,所谓扩张就是向这些位置赋值离大本营0的距离。每次扩张只会访问上下左右的位置。不同阵营的0所遍历过的位置一定是距离所属大本营的那个0最近的,因为这些大本营的每次遍历的层级都是一样的。所以当遇到由不同阵营访问过的位置,不需要再访问。
  5. 因为周围的位置可能是可能也是一个大本营0,所以进行距离赋值的时候还需要对这些位置进行判断,如果为0,那该位置仍为0,如果不为0,那接着判断是否为其他阵营访问过的位置,如果是,则不会访问该位置,如果不是,那就给这个位置进行距离赋值。

为了方便理解,用图围绕上述捋一遍:

  1. 队列中假如有两个0的阵营,每个阵营轮流进行领地扩张,黄色领地先行,绿色领地紧接其后。
    在这里插入图片描述

2. 这一轮黄色领地继续扩张,绿色领地在黄色领地扩张后,也紧接着进行扩张。
在这里插入图片描述

3.最后两个领地都扩张结束了,得到的领地地图,就是我们要返回的矩阵啦。
在这里插入图片描述

  • 实现代码:

    #include <climits>
    #include <vector>
    #include <queue>
    using namespace std;
    class Solution {
    public:
        void bfs(vector<vector<int> >&res, queue<pair<int, int> >& q, int m, int n) 
        {
            vector<vector<int> > dirs{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
            while (!q.empty())
            {
                auto pos = q.front();
                q.pop();
                int dist = res[pos.first][pos.second];
                for (auto& d : dirs)
                {
                    int r = pos.first + d[0];
                    int c = pos.second + d[1];
                    if (r >= 0 && r < m && c >= 0 && c < n)
                    {
                        if (dist + 1 < res[r][c])	//判断res[r][c]是否为0 或 是否为其他0阵营访问过的位置,如果是自己阵营或其他阵营遍历过的位置则不再访问。
                        {
                            res[r][c] = dist + 1;
                            q.push({r, c});
                        }
                    }
                }
            }
            return ;
        }
        vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
            queue<pair<int,int> >q;
            int i, j;
            int m = mat.size(), n = mat[0].size();
            vector<vector<int> > res(m, vector<int>(n, INT_MAX));
            for (i = 0; i < m; ++i)
            {
                for (j = 0; j < n; ++j)
                {
                    if (mat[i][j] == 0)
                    {
                        q.push({i, j});
                        res[i][j] = 0;
                    }
                }
            }
            bfs(res, q, m, n);
            return res;
        }
    };
    

4.总结

​ 知识点:广度优先遍历

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值