1. 题⽬链接:542.01矩阵
2. 题⽬描述:
3. 解法(bfs)(多个源头的最短路问题)
算法思路:
对于求的最终结果,我们有两种⽅式:
• 第⼀种⽅式:从每⼀个1 开始,然后通过层序遍历找到离它最近的0 。
这⼀种⽅式,我们会以所有的1 起点,来⼀次层序遍历,势必会遍历到很多重复的点。并且如果 矩阵中只有⼀个0 的话,每⼀次层序遍历都要遍历很多层,时间复杂度较⾼。
• 换⼀种⽅式:从0 开始层序遍历,并且记录遍历的层数。当第⼀次碰到1 的时候,当前的层数 就是这个1 离0 的最短距离。
这⼀种⽅式,我们在遍历的时候标记⼀下处理过的1 ,能够做到只⽤遍历整个矩阵⼀次,就能得 到最终结果。
但是,这⾥有⼀个问题, 0 是有很多个的,我们怎么才能保证遇到的1 距离这⼀个0 是最近的 呢?
其实很简单,我们可以先把所有的0 都放在队列中,把它们当成⼀个整体,每次把当前队列⾥⾯的所 有元素向外扩展⼀次。
C++算法代码:
class Solution
{
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
vector<vector<int>> updateMatrix(vector<vector<int>>& mat)
{
int m=mat.size(),n=mat[0].size();
vector<vector<int>> answer(m, vector<int>(n, -1)); //答案
queue<pair<int,int>> q; //存储队列
//寻找0点
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(mat[i][j]==0)
{
answer[i][j]=0;
q.push({i,j});
}
}
}
//多节点同时拓展
while(q.size())
{
int lenth=q.size();
for(int i=0;i<lenth;i++)
{
auto[a,b]=q.front();
q.pop();
for(int j=0;j<4;j++)
{
int x=a+dx[j],y=b+dy[j];
if(x>=0&&x<m&&y>=0&&y<n&&answer[x][y]==-1)
{
answer[x][y]=answer[a][b]+1;
q.push({x,y});
}
}
}
}
return answer;
}
};
Java算法代码:
class Solution
{
int[] dx = { 0, 0, -1, 1 };
int[] dy = { 1, -1, 0, 0 };
public int[][] updateMatrix(int[][] mat)
{
int m = mat.length, n = mat[0].length;
// dist[i][j] == -1:标记当前位置没有被搜索过
// dist[i][j] != -1:存的是最短距离
int[][] dist = new int[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
dist[i][j] = -1;
Queue<int[]> q = new LinkedList<>();
// 1. 把所有的源点加⼊到队列⾥⾯
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
if (mat[i][j] == 0)
{
dist[i][j] = 0;
q.add(new int[] {i, j});
}
}
// 2. ⼀层⼀层的往外扩
while (!q.isEmpty())
{
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++)
{
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
{
dist[x][y] = dist[a][b] + 1;
q.add(new int[] {x, y});
}
}
}
return dist;
}
}