算法/BFS/DFS

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;
        }
    }
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值