当前位置: 首页 > article >正文

【4.4】图搜索算法-BFS和DFS两种方式解岛屿数量

一、题目

        给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。

示例 1:
输入:
[
[ '1' , '1' , '1' , '1' , ' 0 ' ] ,
[ '1' , '1' , ' 0 ' , ' 1' , ' 0 ' ] ,
[ '1' , '1' , ' 0 ' , ' 0 ' , ' 0 ' ] ,
[ ' 0 ' , ' 0 ' , ' 0 ' , ' 0 ' , ' 0 ' ]
]
输出: 1


示例 2:
输入:
[
[ '1' , '1' , ' 0 ' , ' 0 ' , ' 0 ' ] ,
[ '1' , '1' , ' 0 ' , ' 0 ' , ' 0 ' ] ,
[ ' 0 ' , ' 0 ' , '1' , ' 0 ' , ' 0 ' ] ,
[ ' 0 ' , ' 0 ' , ' 0 ' , ' 1' , '1' ]
]
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

二、解题思路

DFS解决方式:

        这道题目要求我们计算岛屿的面积,二维数组中值为1的元素表示岛屿。如果多个1是连在一起的,那么它们只能算作一个岛屿。

        最简单的方法是遍历数组中的每一个元素,如果遇到1,说明这是一个岛屿,然后将其置为0(或其他非1的字符),接着遍历其上下左右四个位置。如果这些位置中也有1,说明这些岛屿是相连的,只能算作一个岛屿,我们同样将其置为0,然后再以这些位置为中心,继续遍历它们的上下左右四个位置。如果遇到0,说明这不是岛屿,就不再继续向其上下左右四个位置遍历。以示例1为例:

每个位置只要是1,先要把它置为0,然后沿着他的上下左右4个方向继续遍历,执行同样的操作,要注意边界条件的判断。

BFS解决方式:

        深度优先搜索(DFS)是一种沿着一条路径不断深入的搜索策略,直到遇到终止条件时才会返回。而广度优先搜索(BFS)则是先访问当前位置附近的节点,就像一个不断扩大的圈,先访问圈内的节点,然后再逐步扩大圈的范围继续访问。如下:

这题使用BFS和DFS都能解决,如果遇到位置为1的格子,只要能把他们挨着的为1的全部置为0,然后挨着的挨着的为1的位置也置为0,然后……一直这样循环下去。

三、代码实现

DFS方式:

#include <iostream>
#include <vector>

using namespace std;

void dfs(vector<vector<char>>& grid, int i, int j) {
    // 边界条件判断,不能越界
    if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] == '0')
        return;
    // 把当前格子置为0,然后再从他的上下左右4个方向继续遍历
    grid[i][j] = '0';
    dfs(grid, i - 1, j); // 上
    dfs(grid, i + 1, j); // 下
    dfs(grid, i, j - 1); // 左
    dfs(grid, i, j + 1); // 右
}

int numIslands(vector<vector<char>>& grid) {
    // 边界条件判断
    if (grid.empty() || grid[0].empty())
        return 0;

    int count = 0;

    // 两个for循环遍历每一个格子
    for (int i = 0; i < grid.size(); i++) {
        for (int j = 0; j < grid[0].size(); j++) {
            // 只有当前格子是1才开始计算
            if (grid[i][j] == '1') {
                // 如果当前格子是1,岛屿的数量加1
                count++;
                // 然后通过dfs把当前格子的上下左右4个位置为1的都要置为0,因为他们是连在一起的算一个岛屿
                dfs(grid, i, j);
            }
        }
    }

    // 最后返回岛屿的数量
    return count;
}

int main() {
    vector<vector<char>> grid = {
        {'1', '1', '0', '0', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '1', '0', '0'},
        {'0', '0', '0', '1', '1'}
    };

    int result = numIslands(grid);
    cout << "Number of islands: " << result << endl;

    return 0;
}

BFS方式:

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

void bfs(vector<vector<char>>& grid, int x, int y) {
    int n = grid.size();
    int m = grid[0].size();
    queue<int> queue;

    // 把当前格子先置为0
    grid[x][y] = '0';
    // 把两位数字转化为一位数字并存放到队列中
    int code = x * m + y;
    queue.push(code);

    while (!queue.empty()) {
        // 出队
        code = queue.front();
        queue.pop();
        // 反转成坐标值(i,j)
        int i = code / m;
        int j = code % m;

        // 上
        if (i > 0 && grid[i - 1][j] == '1') {
            grid[i - 1][j] = '0';
            queue.push((i - 1) * m + j);
        }
        // 下
        if (i < n - 1 && grid[i + 1][j] == '1') {
            grid[i + 1][j] = '0';
            queue.push((i + 1) * m + j);
        }
        // 左
        if (j > 0 && grid[i][j - 1] == '1') {
            grid[i][j - 1] = '0';
            queue.push(i * m + j - 1);
        }
        // 右
        if (j < m - 1 && grid[i][j + 1] == '1') {
            grid[i][j + 1] = '0';
            queue.push(i * m + j + 1);
        }
    }
}

int numIslands(vector<vector<char>>& grid) {
    // 边界条件判断
    if (grid.empty() || grid[0].empty())
        return 0;

    int count = 0;

    // 两个for循环遍历每一个格子
    for (int i = 0; i < grid.size(); i++) {
        for (int j = 0; j < grid[0].size(); j++) {
            // 只有当前格子是1才开始计算
            if (grid[i][j] == '1') {
                // 如果当前格子是1,岛屿的数量加1
                count++;
                // 然后通过bfs把当前格子的上下左右4个位置为1的都要置为0,因为他们是连在一起的算一个岛屿
                bfs(grid, i, j);
            }
        }
    }

    return count;
}

int main() {
    vector<vector<char>> grid = {
        {'1', '1', '0', '0', '0'},
        {'1', '1', '0', '0', '0'},
        {'0', '0', '1', '0', '0'},
        {'0', '0', '0', '1', '1'}
    };

    int result = numIslands(grid);
    cout << "Number of islands: " << result << endl;

    return 0;
}

http://www.kler.cn/news/313040.html

相关文章:

  • WPF DataGrid 赋值与修改
  • Spring Boot利用dag加速Spring beans初始化
  • 无人机黑飞打击技术详解
  • 页面关键路径渲染详解
  • Python中使用Scikit-learn进行线性回归分析的实用指南
  • API应用安全风险倍增,F5助企业赢得关键安全挑战
  • esp32s3 NVS空间读写操作
  • Java 每日一刊(第13期):this super static
  • 【Redis入门到精通三】Redis核心数据类型(List,Set)详解
  • Qt 中 `QTimer`定时器的使用方法详解
  • 蓝禾,汤臣倍健,三七互娱,得物,顺丰,快手,游卡,oppo,康冠科技,途游游戏,埃科光电25秋招内推
  • Java并发集合框架:高效多线程数据访问
  • Flask 实现用户登录功能的完整示例:前端与后端整合(附Demo)
  • ubuntu 20.04 ‘Wired Unmanaged‘ 网络无法配置解决方法
  • 政务安全运营核心能力模块
  • Stable Diffusion绘画 | ControlNet应用-instant-ID控制器:快速生成人物多角度图片
  • 大模型——LLaVA和LLaMA的介绍和区别
  • redis-shake v4全量增量同步redis数据
  • 海康VM脚本中使用opencvsharp和halcon
  • HelpLook VS GitBook,在线文档管理工具对比
  • 【工具变量】科技金融试点城市DID数据集(2000-2023年)
  • 论文阅读-《Attention is All You Need》
  • Redis 哨兵模式的选举算法是什么?
  • Python 课程12-Python 自动化应用
  • Java NIO(非阻塞IO)简介
  • 【秋招笔试-支持在线评测】8.28华为秋招(已改编)-三语言题解
  • 算法打卡 Day34(贪心算法)-分发饼干 + 摆动序列 + 最大子序和
  • 《粮油与饲料科技》是什么级别的期刊?是正规期刊吗?能评职称吗?
  • 【设计模式-桥接】
  • Visual Studio 引入外部静态库与动态库