代码随想录算法训练营第四十二天|广度优先搜索理论基础、岛屿数量:深搜版、岛屿数量:广搜版

广度优先搜索理论基础

广搜(bfs)是一圈一圈的搜索过程。因为广搜是从起点出发,以起始点为中心一圈一圈进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路。

广搜的过程:我们从图中可以看出,从start起点开始,是一圈一圈,向外搜索,方格编号1为第一步遍历的节点,方格编号2为第二步遍历的节点,第四步的时候我们找到终止点end。

正是因为BFS一圈一圈的遍历方式,所以一旦遇到终止点,那么一定是一条最短路径。

代码框架:

其实,我们仅仅需要一个容器,能保存我们要遍历过的元素就可以,那么用队列,还是用栈,甚至用数组,都是可以的

用队列的话,就是保证每一圈都是一个方向去转,例如统一顺时针或者逆时针

因为队列是先进先出,加入元素和弹出元素的顺序是没有改变的。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
void bfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
    queue<pair<int, int>> que;
    que.push({})//起始节点加入队列
    visited[x][y] = true;
    while(!que.empty()){
        pair<int, int> cur = que.front();
        que.pop();
        int curx = cur.first();
        int cury = cur.second();
        for(int i=0; i<4; i++){
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1];
            if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
            if(!visited[nextx][nexty]){ // 如果节点没被访问过
                que.push({nextx, nexty}); // 队列添加该节点为下一轮要遍历的节点
                visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
            }
        }
    }

}

99. 岛屿数量:深搜版

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

//N和M表示矩阵的行数和列数
int dir[4][2] = {0,1,1,0,-1,0,0,-1};
void dfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
    for(int i=0; i<4; i++){
        int nextx = x + dir[i][0];
        int nexty = y + dir[i][1];
        if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
        if(!visited[nextx][nexty] && grid[nextx][nexty] == 1){
            visited[nextx][nexty] = true;
            dfs(grid, visited, nextx, nexty);
        }
    }
}

int main(){
    int n, m;
    cin>>n>>m;
    vector<vector<int>> grid(n, vector<int>(m, 0));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>grid[i][j];
        }
    }
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    int result = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!visited[i][j]&&grid[i][j]==1){
                visited[i][j] = true;
                result++;
                dfs(grid, visited, i, j);
            }
        }
    }
    cout<<result<<endl;
}

99. 岛屿数量:广搜版

只要 加入队列就代表 走过,就需要标记,而不是从队列拿出来的时候再去标记走过

如果从队列拿出节点,再去标记这个节点走过,就会发生下图所示的结果,会导致很多节点重复加入队列。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int dir[4][2] = {0,1,1,0,-1,0,0,-1};
void bfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
    queue<pair<int, int>> que;
    que.push({x, y});
    visited[x][y] = true;
    while(!que.empty()){
        pair<int, int> cur = que.front();
        que.pop();
        int curx = cur.first;
        int cury = cur.second;
        for(int i=0; i<4; i++){
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1];
            if(nextx<0||nextx>=grid.size()||nexty<0||nexty>=grid[0].size()) continue;
            if(!visited[nextx][nexty] && grid[nextx][nexty]==1){
                que.push({nextx, nexty});
                visited[nextx][nexty] = true;//只要访问就要标记
            }
        }
    }
}
int main(){
    int n, m;
    cin>>n>>m;
    vector<vector<int>> grid(n, vector<int>(m, 0));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>grid[i][j];
        }
    }
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    int result = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!visited[i][j] && grid[i][j]==1){
                result++;
                bfs(grid, visited, i, j);
            }
        }
    }
    cout<<result<<endl;
}
相关推荐
pianmian11 小时前
python数据结构基础(7)
数据结构·算法
好奇龙猫3 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
香菜大丸4 小时前
链表的归并排序
数据结构·算法·链表
jrrz08284 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time4 小时前
golang学习2
算法
南宫生5 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步6 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara6 小时前
函数对象笔记
c++·算法
泉崎6 小时前
11.7比赛总结
数据结构·算法