给定一个由 0 和 1 组成的矩阵,找出每一个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。web
示例 1: 输入: 0 0 0 0 1 0 0 0 0 输出: 0 0 0 0 1 0 0 0 0 示例 2: 输入: 0 0 0 0 1 0 1 1 1 输出: 0 0 0 0 1 0 1 2 1
注意:
给定矩阵的元素个数不超过 10000。
给定矩阵中至少有一个元素是 0。
矩阵中的元素只在四个方向上相邻: 上、下、左、右。数组
连接:https://leetcode-cn.com/problems/01-matrix数据结构
这里我主要是使用了DFS+剪枝,最好的方法应该是DP(不过我不太会,卑微)。
由于矩阵的元素不超过10000,因此多是110000或者100001大小,若是直接开个数组(10000*10000)去存状态,会爆内存,因此这里咱们使用map这一数据结构去存状态,判断该点有没有访问过。在主函数中,咱们遍历矩阵中的每一个值,若是其值不为0,且相邻不为0(第一个剪枝),则就须要修改,咱们清空map数组,而后进行dfs操做,若是如今点的距离已经大于该点存的值,则就直接退出(第二个剪枝),若是到了0且距离比以前存的更小,则就更新,最后就获得了答案。svg
struct Points { int x; int y; Points(int a, int b) { x = a; y = b; } }; class Solution { int row; int col; // 方向数组 int dirs[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; map<int, map<int, bool> > mp; // 判断有没有超出范围 bool f(int i, int j) { if(i < 0 || j < 0 || i >= row || j >= col) return false; return true; } // 用来剪枝的函数 bool g(int x, int y, vector<vector<int>>& matrix) { for(int i = 0; i < 4; i++) { int xt = x + dirs[i][0]; int yt = y + dirs[i][1]; if(f(xt, yt) && matrix[xt][yt] == 0) return false; } return true; } void dfs(vector<vector<int>>& matrix, int i, int j, int targetx, int targety) { int dis = abs(targetx-i) + abs(targety-j); if(dis >= matrix[targetx][targety]) return ; else if(matrix[i][j] == 0) { if(matrix[targetx][targety] > dis) matrix[targetx][targety] = dis; return ; } else { for(int k = 0; k < 4; k++) { int xt = i + dirs[k][0]; int yt = j + dirs[k][1]; if(f(xt, yt) && !mp[xt][yt]) { mp[xt][yt] = true; // cout << xt << '-' << yt << endl; dfs(matrix, xt, yt, targetx, targety); } } } } public: vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) { row = matrix.size(); if(row == 0) return matrix; col = matrix[0].size(); for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { if(matrix[i][j] != 0 && g(i, j, matrix)) { mp.erase(mp.begin(), mp.end()); matrix[i][j] = row+col; mp[i][j] = 1; dfs(matrix, i, j, i, j); } } } return matrix; } };