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

news2024/11/17 1:38:17

先复习一下什么是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; // 返回岛屿的数量
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1550686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

应急 | BuleHero挖矿蠕虫最新变种分析

背 景 挖矿蠕虫病毒BuleHero擅长利用各类漏洞攻击、弱密码爆破攻击。病毒作者不断更新变种&#xff0c;是近期最活跃的挖矿蠕虫病毒之一。攻击者最新的BuleHero挖矿蠕虫实现入侵后&#xff0c;还会释放挖矿程序&#xff0c;使服务器的资源被消耗挖矿&#xff0c;极大影响正常业…

【EI会议征稿通知】电子、通信与智能科学国际会议(ECIS 2024)

电子、通信与智能科学国际会议&#xff08;ECIS 2024&#xff09; The International Conference on Electronics, Communications and Intelligent Science 电子、通信与智能科学国际会议&#xff08;ECIS 2024&#xff09;将于2024年05月24日-05月27日在中国长沙召开。ECIS…

Electron+Vue构建项目时出错:Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT

问题&#xff1a;ElectronVue构建项目时出错&#xff1a;Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT URL:https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1701 一&#xff0c;构建时node版本要低 同时构建命令如下&#xff1a; "el…

Linux——磁盘与文件系统管理

目录 磁盘分区的表示 硬盘分区 分区类型 确认系统中的磁盘设备——fdisk 规划硬盘中的分区——fdisk 文件系统 文件系统类型&#xff1a; 在分区中创建文件系统——mkfs&#xff0c;mkswap 挂载文件系统 mount命令 umount命令 查看分区挂载情况 设置启动载入&…

CCleaner2024最新版本win系统清理工具功能介绍及下载

CCleaner是一款在计算机领域广受欢迎的系统清理和优化工具。它以其强大的功能、简洁的操作界面和显著的效果&#xff0c;赢得了众多用户的青睐。下面&#xff0c;我将从功能、特点、使用方法以及优势等方面对CCleaner进行详细介绍。 CCleaner下载如下&#xff1a; https://wm.…

调用第三方接口:Http请求工具类

在对接第三方接口时&#xff0c;需要进行数据交互&#xff0c;于是写了一个 Java 的 Http 请求工具类&#xff0c;该工具类可以调用 Get 请求或者 POST 请求。 根据自己业务需求灵活修改&#xff0c;这里写了两个工具类&#xff0c;自己选一个就可以 直接上代码&#xff1a; …

Python模糊字符串匹配工具库之fuzzywuzzy使用详解

概要 Python的fuzzywuzzy库是一个强大的模糊字符串匹配工具,基于Levenshtein距离算法,可用于处理文本相似度匹配任务。本文将深入探讨fuzzywuzzy库的各种功能和用法,结合详细的描述和丰富的示例代码,带领大家全面了解这个工具的使用方法和实际应用场景。 安装 在开始使用…

【技巧】PyTorch限制GPU显存的可使用上限

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 从 PyTorch 1.4 版本开始&#xff0c;引入了一个新的功能 torch.cuda.set_per_process_memory_fraction(fraction, device)&#xff0c;这个功能允许用户为特定的 GPU 设备设置进程可使用的显存上限比例。 测试代…

第115讲:Mycat核心配置文件各项参数的作用以及概念

文章目录 1.Mycat配置文件相关概念2.Schema配置文件3.Rule配置文件4.Server配置文件 1.Mycat配置文件相关概念 在Mycat中核心的配置文件有schema.xml和rule.xml以及server.xml三个&#xff0c;其中schema.xml是用来配置数据库、表、读写分离、分片节点、分片规则等信息&#x…

uniapp对接萤石云 实现监控播放、云台控制、截图、录像、历史映像等功能

萤石云开发平台地址&#xff1a;文档概述 萤石开放平台API文档 (ys7.com) 萤石云监控播放 首先引入萤石云js js地址&#xff1a;GitHub - Ezviz-OpenBiz/EZUIKit-JavaScript-npm: 轻应用npm版本&#xff0c;降低接入难度&#xff0c;适配自定义UI&#xff0c;适配主流框架 vi…

DC电源模块的设计与制造流程

BOSHIDA DC电源模块的设计与制造流程 DC电源模块是一种用于将交流电转换为直流电的设备。它广泛应用于各种电子设备中&#xff0c;如电子产品、工业仪器、电视等。下面是DC电源模块的设计与制造流程的简要描述&#xff1a; 1. 需求分析&#xff1a;在设计DC电源模块之前&#…

目标检测——服装数据集

一、重要性及意义 首先&#xff0c;服装检测是确保产品质量和安全性的关键环节。通过对服装的材质、工艺、安全性等方面的检测&#xff0c;可以及时发现并纠正可能存在的缺陷和问题&#xff0c;从而确保产品符合消费者的期望和要求。这有助于维护品牌形象&#xff0c;提高消费…

【Java程序设计】【C00360】基于Springboot的考研互助交流平台(有论文)

基于Springboot的考研互助交流平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及i…

day70 Mybatis使用mapper重构xml文件重新修改商品管理系统

day67 基于mysql数据库jdbcDruidjar包连接的商品管理用户购物系统-CSDN博客 1多表操作 2动态SQL 项目中使用的为商品管理系统的表 一 查询商品信息 编号&#xff0c;名称&#xff0c;单价&#xff0c;库存&#xff0c;类别 1表&#xff1a;商品表&#xff0c;类别表 n对1…

el-table中复选框、展开列、索引

<!-- 复选框&#xff0c;搭配selection-change"handleSelectChange"使用&#xff0c;每次点击复选框就会调用方法handleSelectChange(selection) {}&#xff0c;在该方法中只要调用该方法获取到的selection就是所有已勾选的记录集合 --> <el-table-column t…

【正点原子FreeRTOS学习笔记】————(14)事件标志组

这里写目录标题 一、事件标志组简介&#xff08;了解&#xff09;二、事件标志组相关API函数介绍&#xff08;熟悉&#xff09;三、事件标志组实验&#xff08;掌握&#xff09; 一、事件标志组简介&#xff08;了解&#xff09; 事件标志位&#xff1a;用一个位&#xff0c;来…

网站可扩展架构设计

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、可扩展性架构简介 1.可扩展性是什么 可扩展性指系统为了应对将来需求变化而提供的一种扩展能力&#xff0c;当有新的需求出现时&#xff0c;系…

剑指Offer题目笔记19(二分查找)

面试题68&#xff1a; 问题&#xff1a; ​ 输入一个排序的整形数组nums和一个目标值t&#xff0c;如果数组nums中包含t&#xff0c;则返回在数组中的下标&#xff0c;否则返回按照顺序插入到数组的下标。 解决方案&#xff1a; ​ 使用二分查找。每次二分查找都选取位于数组…

CIM搭建实现发送消息的效果

目录 背景过程1、下载代码2、进行配置3、直接启动项目4、打开管理界面5、启动web客户端实例项目6、发送消息 项目使用总结 背景 公司项目有许多需要发送即时消息的场景&#xff0c;之前一直采用的是传统的websocket连接&#xff0c;它会存在掉线严重&#xff0c;不可重连&…

PCB经常连锡?或许你可以看看这三个焊盘

在印刷电路板&#xff08;PCB&#xff09;制造中&#xff0c;很容易遇见连锡问题&#xff0c;即相邻焊盘之间出现意外的锡桥连接&#xff0c;这主要是焊盘的设置不当&#xff0c;若是不及时处理&#xff0c;很可能导致电路短路&#xff0c;影响其正常功能。那么如何选择焊盘&am…