题目链接
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
法1:BFS
一开始我是这么想的,遍历每一个1,然后从1搜索到0…
后来发现,从0搜到1就更快,一下子可以解得很多个格子。
初始队列:把0全部入队,然后进行BFS,遇到1的时候就记录此时的BFS遍数(level)
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int n=mat.size(),m=mat[0].size();
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
vector<vector<int>> res(n,vector<int>(m));
queue<pair<int,int>> q;
int level=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mat[i][j]==0)
{
q.push({i,j});
res[i][j]=0;
}
else mat[i][j]=-1;
}
}
while(!q.empty())
{
int size=q.size();
level++;
for(int i=0;i<size;i++)
{
int topx=q.front().first;
int topy=q.front().second;
q.pop();
for(int k=0;k<4;k++)
{
int tx=topx+dx[k];
int ty=topy+dy[k];
if(tx>=0&&ty>=0&&tx<n&&ty<m&&mat[tx][ty]==-1)
{
q.push({tx,ty});
res[tx][ty]=level;
mat[tx][ty]=1;
}
}
}
}
return res;
}
};
法2:DP(二维)
有了DP这个想法之后,状态转移方程是比较好想的。
对一个点1,与它相关的有上下左右四个格子,那么显然一遍遍历是不够的,因为从上至下,总左至又会导致两个关联格子的结果还没出来。
那么就把这个转移方程分为两个过程,第一次从左上遍历到右下,只关心左边和上边的格子;第二次从右下遍历到左上,只关心右边和下边的格子。
class Solution {
public:
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int n=mat.size(),m=mat[0].size();
vector<vector<int>> dp(n,vector<int>(m,100000));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mat[i][j]==0) dp[i][j]=0;
else
{
if(j>0) dp[i][j]=min(dp[i][j],dp[i][j-1]+1);
if(i>0) dp[i][j]=min(dp[i][j],dp[i-1][j]+1);
}
}
}
for(int i=n-1;i>=0;i--)
{
for(int j=m-1;j>=0;j--)
{
if(mat[i][j]!=0)
{
if(i<n-1) dp[i][j]=min(dp[i][j],dp[i+1][j]+1);
if(j<m-1) dp[i][j]=min(dp[i][j],dp[i][j+1]+1);
}
}
}
return dp;
}
};