一题学会BFS和DFS,手撕不再怕

简介: 一题学会BFS和DFS,手撕不再怕

先复习一下什么是BFS和DFS,各位读者接着往下看就行

BFS算法

BFS类似于树的层次遍历过程,从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

舍去空间换时间。

算法思路

队列(先进先出)

1、创建一个空队列queue(用来存放节点)和一个空列表visit(用来存放已访问的节点)


2、依次将起始点及邻接点加入queue和visit中


3、pop出队列中最先进入的节点,从图中获取该节点的邻接点


4、如果邻接点不在visit中,则将该邻接点加入queue和visit中


5、输出pop出的节点


6、重复3、4、5,直至队列为空

DFS算法

DFS沿着树的深度遍历树的节点,

选一条路一直走到底,回溯,遍历所有的子节点,进而达到全局搜索的目的。

算法思路

栈(先进后出)

和BFS相似,只是稍微做了一丝改变


1、创建一个空栈stack(用来存放节点)和一个空列表visit(用来存放已访问的节点)


2、依次将起始点及邻接点加入stack和visit中


3、poo出栈中最后进入的节点,从图中获取该节点的邻接点


4、如果邻接点不在visit中,则将该邻接点加入stack和visit中


5、输出pop出的节点


6、重复3、4、5,直至栈为空

接下来以LeetCode的一道经典题为背景来强化一下写法。


给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。


岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。


此外,你可以假设该网格的四条边均被水包围。


输入:grid = [

 ["1","1","1","1","0"],

 ["1","1","0","1","0"],

 ["1","1","0","0","0"],

 ["0","0","0","0","0"]

]

输出:1


输入:grid = [

["1","1","0","0","0"],

["1","1","0","0","0"],

["0","0","1","0","0"],

["0","0","0","1","1"]

]

输出:3

题目很经典的BFS和DFS都能做,遍历就行

DFS题解

       我们可以将二维网格看成一个无向图,竖直或水平相邻的 1 之间有边相连。为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索。在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。最终岛屿的数量就是我们进行深度优先搜索的次数。

代码:

class Solution {
public:
    // 深度优先搜索函数,用于将当前岛屿中所有相连的陆地标记为已访问('0')
    void dfs(vector<vector<char>>& grid, int i, int j) {
        int n = grid.size(); // 获取网格的行数
        int m = grid[0].size(); // 获取网格的列数
        grid[i][j] = '0'; // 将当前位置标记为已访问
        // 检查当前位置的上、下、左、右四个方向是否有相邻的陆地,如果有,则继续深度优先搜索
        if (i - 1 >= 0 && grid[i - 1][j] == '1') dfs(grid, i - 1, j); // 上
        if (i + 1 < n && grid[i + 1][j] == '1') dfs(grid, i + 1, j); // 下
        if (j - 1 >= 0 && grid[i][j - 1] == '1') dfs(grid, i, j - 1); // 左
        if (j + 1 < m && grid[i][j + 1] == '1') dfs(grid, i, j + 1); // 右
    }
    
    // 主函数,用于计算网格中岛屿的数量
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size(); // 获取网格的行数
        if (!n) return 0; // 如果网格为空,则返回岛屿数量为0
        int m = grid[0].size(); // 获取网格的列数
        int res = 0; // 用于记录岛屿的数量
        // 遍历整个网格
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // 如果当前位置是陆地('1'),则进入深度优先搜索,将与之相连的所有陆地标记为已访问,并将岛屿数量加一
                if (grid[i][j] == '1') {
                    res++; // 岛屿数量加一
                    dfs(grid, i, j); // 深度优先搜索,将与当前陆地相连的所有陆地标记为已访问
                }
            }
        }
        return res; // 返回岛屿的数量
    }
};

BFS题解

       同样地,我们也可以使用广度优先搜索代替深度优先搜索。为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则将其加入队列,开始进行广度优先搜索。在广度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。直到队列为空,搜索结束。最终岛屿的数量就是我们进行广度优先搜索的次数  

代码:

class Solution {
public:
    // 计算岛屿数量的函数
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size(); // 获取网格的行数
        if (!n) return 0; // 如果网格为空,则返回岛屿数量为0
        int m = grid[0].size(); // 获取网格的列数
        int res = 0; // 用于记录岛屿的数量
        // 遍历整个网格
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // 如果当前位置是陆地('1'),则进入广度优先搜索,将与之相连的所有陆地标记为已访问,并将岛屿数量加一
                if (grid[i][j] == '1') {
                    res++; // 岛屿数量加一
                    grid[i][j] = '0'; // 将当前位置标记为已访问
                    queue<pair<int,int>> neighbors; // 创建一个队列用于存储当前岛屿相邻的陆地
                    neighbors.push({i, j}); // 将当前位置加入队列
                    while (!neighbors.empty()) { // 循环直到队列为空
                        auto t = neighbors.front(); // 取出队首元素
                        neighbors.pop(); // 弹出队首元素
                        int row = t.first, col = t.second; // 获取当前位置的行和列
                        // 检查当前位置的上、下、左、右四个方向是否有相邻的陆地,如果有,则将其加入队列,并标记为已访问
                        if (row + 1 < n && grid[row + 1][col] == '1') {
                            neighbors.push({row + 1, col});
                            grid[row + 1][col] = '0';
                        }
                        if (row - 1 >= 0 && grid[row - 1][col] == '1') {
                            neighbors.push({row - 1, col});
                            grid[row - 1][col] = '0';
                        }
                        if (col + 1 < m && grid[row][col + 1] == '1') {
                            neighbors.push({row, col + 1});
                            grid[row][col + 1] = '0';
                        }
                        if (col - 1 >= 0 && grid[row][col - 1] == '1') {
                            neighbors.push({row, col - 1});
                            grid[row][col - 1] = '0';
                        }
                    }
                }
            }
        }
        return res; // 返回岛屿的数量
    }
};
相关文章
|
5月前
|
算法
数据结构与算法-DFS+BFS篇(迷宫问题)
数据结构与算法-DFS+BFS篇(迷宫问题)
68 3
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(2)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(2)
112 0
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(3)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(3)
109 0
|
算法 定位技术
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(7)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(7)
99 0
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(9)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(9)
87 0
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(1)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(1)
119 0
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(4)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(4)
95 0
|
算法 BI
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(5)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(5)
103 0
|
安全 算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(6)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(6)
102 0
|
算法
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(10)
【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(10)
117 0