本文分享自华为云社区《BFS和DFS算法初探》,作者: ayin。

本次分享两个常见的搜索算法
1.BFS 即广度优先搜索
2.DFS 即深度优先搜索

岛屿数量

给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。

  • 示例 1:
11110
11010
11000
00000

输出: 1

  • 示例 2:
11000
11000
00100
00011

输出: 3

其实我们还是比较容易想到初步解法的,即从二维网络某点出发,寻找其四周相邻的陆地,直到所有包含的点都没有相邻的陆地为止,这里可以认为已经找到了一个岛屿,其余岛屿同理可以找到。这里的关键问题是遍历岛屿的顺序,其实不难看出有两种顺序

  • a.
  1. 优先寻找某a节点的所有相邻位置
  2. 然后拿出一个相邻位置比如说b寻找其所有相邻位置
  3. 拿出a节点下一个相邻位置重复第2步直到a节点的相邻位置都执行过该操作
  4. 拿出b,重复1,2,3步
  • b.
  1. 优先寻找a节点的相邻位置比如说b
  2. 寻找b的相邻位置c
  3. 直到没有相邻位置后再返回到a的下一个相邻位置,重复1,2步

方案一

我们对第一种方法进行观察:

  1. 越是接近根结点的结点将越早地遍历
  2. 思考用什么存储结构来存放我们找到的位置:我们把root的相邻位置存储到x结构中,然后取出x的某个相邻位置a,寻找其相邻位置继续存放到x中,再取出x中与root相邻的下个位置b继续寻找其相邻位置放入x中。这里我们发现我们存储x的顺序与我们处理x得到其他数据的顺序一致:先进先出(FIFO),不难得出我们可以采用队列来存储
  3. 需要一种方法避免对已经找到的位置重复访问

现在可以尝试写出实际的程序

 public int numIslands(char[][] grid) {if (grid.length==0){return 0;}Queue<Point> queue = new LinkedList<>();int count =0;for(int y=0;y<grid.length;y++){for(int x=0;x<grid[0].length;x++){// 核心部分if(grid[y][x]=='1'){queue.offer(new Point(x,y));while (queue.size() != 0) {Point nowPoint = queue.peek();List<Point> pointList = getNearPoints(nowPoint, grid);for (Point point : pointList) {queue.offer(point);// 标记已经访问的位置grid[point.y][point.x] = '2';System.out.println(point.y * grid[0].length + point.x);}queue.poll();}count++;}// 核心部分}}

通过这个实例我们可以进一步抽象为图论中的一种算法–BFS
可以参考leetcode的动图和算法模板来加深印象

方案二

同样来观察第二中方法,我们发现

  1. 优先走完一条路径直到结束
  2. 我们需要在某一路径结束后,回溯到初始位置,即存储节点位置的顺序和处理的顺序相反,即现进后出(FILO)。这里我们可以用递归或者栈来处理。

试着写出实际的程序

  1. 递归
 public int numIslands(char[][] grid) {int len = 0;Set <Integer> visited = new HashSet<>();for (int y = 0; y < grid.length; y++) {for (int x = 0; x < grid[0].length; x++) {Integer node = y * grid[0].length + x;if (!visited.contains(node)&&grid[y][x] == '1') {visited.add(node);DFS3(node, visited, grid);len++;}}}return len;}boolean DFS(Integer cur, Set<Integer> visited,char [][]grid) {for (Integer next : getNearNodes(cur,grid[0].length,grid.length,grid)) {if (!visited.contains(next)) {visited.add(next);System.out.println(next);DFS(next,visited,grid);}}return true;}

2.栈

 boolean DFS3(Integer cur, Set<Integer> visited,char [][]grid){Stack<Integer> nodeStack = new Stack<>();nodeStack.push(cur);while(!nodeStack.empty()){Integer node = nodeStack.peek();boolean hasNearNode = false;for(Integer next:getNearNodes(node,grid[0].length,grid.length,grid)){if(!visited.contains(next)){visited.add(next);nodeStack.push(next);hasNearNode = true;}}// 如果当前节点没有邻居则去除栈顶节点if(!hasNearNode){nodeStack.pop();}}return true;}

通过这个实例我们可以进一步抽象为图论中的一种算法–DFS
参考leetcode的动图和模板算法(递归和栈)来加深印象

点击关注,第一时间了解华为云新鲜技术~​

分享两个常见的搜索算法:BFS和DFS相关推荐

  1. 记录两种搜索遍历算法——BFS和DFS

    " 你所有流过的泪,是一条渡你的河, 你所有受过的苦,将照亮你前方的路:岁月从没有放过我们,我们也不能辜负岁月." 最近过的不好~ 被虐 自信全无 各种害怕.自卑~ 唯有努力前行, ...

  2. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) 阅读本文前,请确保你已经掌握了递归.栈和队列的基本知识,如想掌握搜索的代码实现,请确保你能够用代码实现栈和队列的基本操作. 深度优先遍 ...

  3. BFS和DFS优先搜索算法

    4.教你通透彻底理解:BFS和DFS优先搜索算法 作者:July  二零一一年一月一日 --------------------------------- 本人参考:算法导论  本人声明:个人原创,转 ...

  4. Pandas数据探索分析,分享两个神器!

    在使用 pandas 进行数据分析时,进行一定的数据探索性分析(EDA)是必不可少的一个步骤,例如常见统计指标计算.缺失值.重复值统计等. 使用 df.describe() 等函数进行探索当然是常见操 ...

  5. 协同过滤算法_利用数据分析量化协同过滤算法的两大常见难题

    点击上方"蓝色字体",选择 "设为星标" 关键讯息,D1时间送达! 推荐系统自从问世以来解决了许多不同的商业产品问题,深受广大互联网从业者的喜爱.传统的互联网电 ...

  6. 处理接口幂等性的两种常见方案

    在上周发布的 TienChin 项目视频中,我和大家一共梳理了六种幂等性解决方案,接口幂等性处理算是一个非常常见的需求了,我们在很多项目中其实都会遇到.今天我们来看看两种比较简单的实现思路. 1. 接 ...

  7. 深度优先搜索算法(Depth-First-Search,DFS)与广度优先搜索算法(Breadth-First Search,BFS)理解

    最近学习到了这两种经典的算法,谈一下自己的理解 深度优先搜索算法(Depth-First-Search,DFS) 这个算法会尽可能深的搜索树的分支.当节点v的所在边都己被探寻过,搜索将回溯到发现节点v ...

  8. OFD格式文件怎么转图片?分享两种OFD转图片方法

    OFD格式的文件怎么转换成图片呢?大家在办公中如果收到对方发来的OFD格式文件时,不知道怎么打开文件,从而影响我们的正常工作进度.实际上,这种格式的文件一般是需要使用相关的阅读工具才能够打开,但是我们 ...

  9. 如何去除视频水印?分享两种去除视频水印的方法

    怎么去除掉视频的水印呢?视频水印可能会导致视觉上的干扰,尤其是当水印被放置在视频的重要区域时,例如在视频的中心或底部.此外,在视频制作过程中使用有水印的素材也可能会影响最终的视频质量,因为水印可能会干 ...

最新文章

  1. 资料分享:数学建模资料分享 -- 图论部分
  2. Netty:option和childOption参数设置说明
  3. 实战Nginx与PHP(FastCGI)的安装、配置与优化
  4. OO实现ALV TABLE 四:ALV的显示样式
  5. android 耳机检测,android – 检测耳机是否有麦克风
  6. 使用 JavaScript 实现简单候选项推荐功能(模糊搜索)【收藏】【转】
  7. Java实现一个简单的加密解密方法
  8. mysql account locked_ORA-28000: the account is locked用户锁定问题排查解决
  9. 数据结构与算法之六堆排序
  10. 手动释放linux服务器内存
  11. java final关键字
  12. linux添加凤凰引导,凤凰系统率先升级内核到Linux4.9
  13. input标签的type属性汇总
  14. openwrt 认证收费_openwrt,wifi认证-nodogsplash
  15. 华为手机录制屏幕视频的详细操作
  16. Mac自带的邮件 添加邮箱 无法验证账户或密码【已解决】
  17. 我的面试经历(2013.5)
  18. OpenCalib:自动驾驶多传感器开源标定工具箱
  19. 面向对象基础——方法重载
  20. 期末大作业纯前端技术实现个人简历模板

热门文章

  1. 这就是为什么您的开源项目失败
  2. 明了 | MongoDB 外键的基本使用
  3. localStorage sessionStorage
  4. addEventListener方法与on事件的区别
  5. CSS 文本缩进text-indent属性
  6. ECMAScript 的发展历史
  7. blob数据类型_MySQL 8.0 基本操作步骤:3.字段和数据类型的选择
  8. z变换解差分方程例题_某些常见微分方程的一般解法(工具向)
  9. caffe,caffe2 and pytorch
  10. PCIe总线基本概念