BFS和DFS不同的应用场景:
1)BFS:BFS 可以看成是层序遍历。从某个结点出发,BFS 首先遍历到距离为 1 的结点,然后是距离为 2、3、4…… 的结点。因此,BFS 可以用来求最短路径问题。BFS 先搜索到的结点,一定是距离最近的结点。
BFS求最短路径问题的模板:
depth = 0 # 记录遍历到第几层,也即路径距离
while queue 非空:
depth++
n = queue 中的元素个数
循环 n 次:
node = queue.pop()
for node 的所有相邻结点 m:
if m 未访问过:
queue.push(m)
2)DFS:递归求解,通常用于求最长距离
1.542. 01 矩阵
题目描述:
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例:
解答描述:
该题要求每个位置到最近的0的距离,而每个位置取值分两种情况:
1)值为0,到最近的0的距离也为0,;
2)值为1,以该位置为起点进行BFS按层扩展BFS,到达有0的位置的层数即为最短距离。
代码:
先将所有的0入队:
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) {
vector<vector<int>> ans;
int rows=mat.size();
int cols=mat[0].size();
queue<pair<int,int> > q;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(mat[i][j]==0)//将所有的0入队
{
q.emplace(i,j);
}
else
{
mat[i][j]=-1;//将所有未访问过的1的距离改为-1,避免和距离1混
}
}
}
//BFS
while(!q.empty())
{
int x=q.front().first;
int y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int new_x=x+dx[i];
int new_y=y+dy[i];
if(new_x>=0 && new_x<rows && new_y>=0 && new_y<cols && mat[new_x][new_y]==-1 )
{
mat[new_x][new_y]=mat[x][y]+1;
q.emplace(new_x,new_y);
}
}
}
return mat;
}
};
先将0邻近的1入队:
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 rows=mat.size();
int cols=mat[0].size();
// vector<vector<int> > ans;
vector<vector<int>> ans(rows, vector<int>(cols,0));//vector初始化为0
queue<pair<int,int> > q;
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(mat[i][j]==0)//将所有的0边上的1入队
{
for(int k=0;k<4;k++){
int new_x=i+dx[k];
int new_y=j+dy[k];
if(new_x>=0 && new_x<rows && new_y>=0 && new_y<cols && mat[new_x][new_y]==1 && ans[new_x][new_y]==0)
{
ans[new_x][new_y]=1;
q.emplace(new_x,new_y);
}
}
}
}
}
//BFS
while(!q.empty())
{
int x=q.front().first;
int y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int new_x=x+dx[i];
int new_y=y+dy[i];
if(new_x>=0 && new_x<rows && new_y>=0 && new_y<cols && mat[new_x][new_y]==1 && ans[new_x][new_y]==0)
{
ans[new_x][new_y]=ans[x][y]+1;
q.emplace(new_x,new_y);
}
}
}
return ans;
}
};
2.994. 腐烂的橘子
题目描述:
在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。
示例:
解答描述:
该题要求直到单元格中没有新鲜橘子为止所必须经过的最小分钟数,也即求从腐烂橘子到达所有的新鲜橘子的最小距离的最大值。
先将所有的腐烂橘子入队,然后进行多源BFS层序遍历,并在层序遍历过程中将遇到的新鲜橘子编腐烂入队,作为下一层节点,当没有新鲜橘子或者腐烂橘子全部出队时,结束BFS。
代码:
class Solution {
public:
int orangesRotting(vector<vector<int>>& grid) {
int rows=grid.size();
int cols=grid[0].size();
queue<pair<int,int>> q;
int fresh_cnt=0;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int max_time=0;
for(int i=0;i<rows;i++)//将所有的腐烂橘子入队,作为第0层节点并且统计新鲜橘子的数量
{
for(int j=0;j<cols;j++)
{
if(grid[i][j]==2)
{
q.emplace(i,j);
}
else if(grid[i][j]==1)
{
fresh_cnt++;
}
}
}
//多源BFS
while(fresh_cnt>0 && !q.empty())//注意条件fresh_cnt不能少,否则会多计算
{
int len=q.size();
for(int k=0;k<len;k++)//逐层处理,每经过一层 maxtime++
{
int x=q.front().first;
int y=q.front().second;
q.pop();
for(int i=0;i<4;i++)
{
int new_x=x+dx[i];
int new_y=y+dy[i];
if(new_x>=0 && new_x<rows && new_y>=0 && new_y<cols && grid[new_x][new_y]==1)
{
grid[new_x][new_y]=2;//新鲜橘子被腐烂
fresh_cnt--;//新鲜橘子数量减1
q.emplace(new_x,new_y);
}
}
}
max_time++;
}
if(fresh_cnt>0)
{
return -1;
}
else{
return max_time;
}
}
};