542. 01 矩阵
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例 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。
- 矩阵中的元素只在四个方向上相邻: 上、下、左、右。
BFS方法,执行时间为304ms
class Solution { public: vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}}; queue<pair<int, int>> q; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (matrix[i][j] == 0) q.push({i, j}); else matrix[i][j] = INT_MAX; } } while (!q.empty()) { auto t = q.front(); q.pop(); for (auto dir : dirs) { int x = t.first + dir[0], y = t.second + dir[1]; if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] <= matrix[t.first][t.second]) continue; matrix[x][y] = matrix[t.first][t.second] + 1; q.push({x, y}); } } return matrix; } };
执行时间为196ms
二次扫描的解法,从而不用使用BFS了。这种解法也相当的巧妙,首先建立一个和matrix大小相等的矩阵res,初始化为很大的值,这里我们用INT_MAX-1。然后遍历matrix矩阵,当遇到为0的位置,将结果res矩阵的对应位置也设为0。这个解法的精髓,如果不是0的地方,在第一次扫描的时候,比较其左边和上边的位置,取其中较小的值,再加上1,来更新结果res中的对应位置。这里就明白了为啥要初始化为INT_MAX-1了,因为这里要加1,如果初始化为INT_MAX就会整型溢出,不过,由于是取较小值,res[i][j]永远不会取到INT_MAX,所以不会有再加1溢出的风险。第一次遍历比较了左和上的方向,那么我们第二次遍历就要比较右和下的方向,注意两种情况下不需要比较,一种是当值为0时,还有一种是当值为1时,这两种情况下值都不可能再变小了,所以没有更新的必要,参见代码如下:
class Solution { public: vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); vector<vector<int>> res(m, vector<int>(n, INT_MAX - 1)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (matrix[i][j] == 0) res[i][j] = 0; else { if (i > 0) res[i][j] = min(res[i][j], res[i - 1][j] + 1); if (j > 0) res[i][j] = min(res[i][j], res[i][j - 1] + 1); } } } for (int i = m - 1; i >= 0; --i) { for (int j = n - 1; j >= 0; --j) { if (res[i][j] != 0 && res[i][j] != 1) { if (i < m - 1) res[i][j] = min(res[i][j], res[i + 1][j] + 1); if (j < n - 1) res[i][j] = min(res[i][j], res[i][j + 1] + 1); } } } return res; } };
用时172ms的解法:
class Solution { public: vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) { vector<vector<int>>result; int m=matrix.size(); if(m==0) return result; int n=matrix[0].size(); result=vector<vector<int>>(m,vector<int>(n,n*m+1)); for(int i=0;i<n;++i) { if(matrix[0][i]==0) result[0][i]=0; for(int j=1;j<m;++j) { if(matrix[j][i]==0) result[j][i]=0; result[j][i]=min(result[j][i],1+result[j-1][i]); } } for(int i=0;i<n;++i) { if(matrix[m-1][i]==0) result[m-1][i]=0; for(int j=m-2;j>=0;--j) { if(matrix[j][i]==0) result[j][i]=0; result[j][i]=min(result[j][i],1+result[j+1][i]); } } for(int i=0;i<m;++i) { if(matrix[i][0]==0) result[i][0]=0; for(int j=1;j<n;++j) { if(matrix[i][j]==0) result[i][j]=0; result[i][j]=min(result[i][j],1+result[i][j-1]); } } for(int i=0;i<m;++i) { if(matrix[i][n-1]==0) result[i][n-1]=0; for(int j=n-2;j>=0;--j) { if(matrix[i][j]==0) result[i][j]=0; result[i][j]=min(result[i][j],1+result[i][j+1]); } } return result; } };