- 剑指 Offer II 107. 矩阵中的距离
- 一、题目
- 1.题目描述
- 2.基础框架
- 3.解题思路
- 4.总结
1.题目描述原题链接:Offer II 107. 矩阵中的距离
给定一个由 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]]
提示:
- 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++基础框架代码如下:
vector3.解题思路> updateMatrix(vector >& mat){ }
- 题目分析
- 题目目标是返回矩阵,其中每个单元格子中的值为到最近0的距离。
- 可以从矩阵中0对应的位置出发,分别对它们进行广度优先遍历周围的位置,从而周围位置得到距离0位置的值。
- 为了得到矩阵中所有0的位置,需要遍历一次矩阵mat,并将0的位置以pair类型存入队列q中。
- 开始时队列中都是0,分别从0出发,对它们的周围的位置进行扩张,所谓扩张就是向这些位置赋值离大本营0的距离。每次扩张只会访问上下左右的位置。不同阵营的0所遍历过的位置一定是距离所属大本营的那个0最近的,因为这些大本营的每次遍历的层级都是一样的。所以当遇到由不同阵营访问过的位置,不需要再访问。
- 因为周围的位置可能是可能也是一个大本营0,所以进行距离赋值的时候还需要对这些位置进行判断,如果为0,那该位置仍为0,如果不为0,那接着判断是否为其他阵营访问过的位置,如果是,则不会访问该位置,如果不是,那就给这个位置进行距离赋值。
为了方便理解,用图围绕上述捋一遍:
- 队列中假如有两个0的阵营,每个阵营轮流进行领地扩张,黄色领地先行,绿色领地紧接其后。
2. 这一轮黄色领地继续扩张,绿色领地在黄色领地扩张后,也紧接着进行扩张。
3.最后两个领地都扩张结束了,得到的领地地图,就是我们要返回的矩阵啦。
-
实现代码:
#include
#include #include using namespace std; class Solution { public: void bfs(vector >&res, queue >& q, int m, int n) { vector > 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 > updateMatrix(vector >& mat) { queue >q; int i, j; int m = mat.size(), n = mat[0].size(); vector > res(m, vector (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; } };
知识点:广度优先遍历



