今天周末,心血来潮打开LeetCode做一道题:
https://leetcode-cn.com/problems/number-of-enclaves/
看到题,我的第一想法是:
从边缘的陆地开始,找到它的最大连通区域。找到的连通区域设置标记位,避免找重复。所有边缘陆地的连通区域都找完以后,没有被标记的陆地就是飞地。

找连通区域,是图的深度优先搜索和广度优先搜索的经典问题。

  1. 识别图上的起点。这里四条边的每个陆地都是起点。将它们保存到队列中。
  2. 通过深度优先搜索,构建一个陆地的连通图。
  3. 通过广度优先搜索,构建一个陆地的连通图。

由于队列中所有符合条件的陆地起点(四个边上的陆地),所以遍历到最后,可以获得所有的陆地连通图。

深度优先搜索

从起点出发,沿着一条边搜索,直到到达终点,得到一条完整的边。这时再回到上一次分叉的起点。进行下一条边的搜索。这种回到分叉点,意味着要用先入后出的栈结构

广度优先搜索

从起点出发,将它的相邻节点放到队列中。再找这些节点的相邻节点。直到找到所有的相邻节点。

不管是DFS还是WFS,为保证所有的节点被搜索,按照固定的顺序(节点有三个子节点,从左到右或者从右到左依次处理)进行搜索。

Java的ArrayDeque

java.util.ArrayDeque,既可以作为栈结构,也可以作为队列结构。

ArrayDeque作为堆栈

要在Java中实现LIFO(后进先出)堆栈,建议在Stack类上使用双端队列。该ArrayDeque类比Stack类快。

ArrayDeque 提供了以下可用于实现堆栈的方法。

push() - 在堆栈顶部添加一个元素

peek() - 从堆栈顶部返回一个元素

pop() - 返回并从堆栈顶部删除元素

ArrayDeque作为队列

ArrayDeque是一个双端队列。
将元素插入双端队列
1.使用add(),addFirst()和addLast()添加元素。满了抛异常IllegalStatementException

add() - 将指定的元素插入ArrayDeque双端队列的末尾

addFirst() -在双端队列的开头,插入指定的元素

addLast() - 在双端队列的末尾插入指定的内容(等效于add())

2 使用remove() ,removeFirst()和removeLast() 返回并删除元素。如果没有可以删除的元素抛异常IllegalStatementException。其中remove等同于removeFirst

3 使用 offer(),offerFirst()和offerLast()插入元素。offer返回并在队尾插入元素,如果插入失败,返回false。

4 使用 poll() pollFirst pollLast删除元素。poll返回并删除双端队列的第一个元素。pollFirst等同于poll。

add和offer从队尾插入元素,失败的情况下add会抛异常。
remove和poll从队首删除元素,失败的情况下remove会抛异常。

DFS和WFS的题解

DFS用ArrayDeque作为栈:方法offer和poll
WFS用ArrayDeque作为队列:方法push和pop
(即取出的是最先放进去的还是最后放进去的元素。

DFS

package graph.connected_land;import java.util.ArrayDeque;public class Dfs {static class Solution {int [][] neighbors = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};public int numEnclaves(int[][] grid) {int rows = grid.length;int cols = grid[0].length;ArrayDeque<int[]> searched = new ArrayDeque<int[]>();boolean[][] visited = new boolean[rows][cols];for (int i = 0; i < rows; i++) {if (grid[i][0] == 1) {searched.push(new int[]{i, 0});visited[i][0] = true;}if (grid[i][cols-1] == 1) {searched.push(new int[]{i, cols-1});visited[i][cols-1] = true;}}for (int i=1; i < cols-1; i++ ) {if (grid[0][i] == 1) {searched.push(new int[]{0, i});visited[0][i] = true;}if (grid[rows-1][i] == 1) {searched.push(new int[]{rows-1, i});visited[rows-1][i] = true;}}while(!searched.isEmpty()) {int[] c = searched.pop();for (int[] neighbor : neighbors) {int x = c[0] + neighbor[0];int y = c[1] + neighbor[1];System.out.println("x " + x + "y " + y);if (x < 0 || x > rows-1 || y < 0 || y > cols-1 || visited[x][y] ){continue;}if (grid[x][y] == 1) {searched.push(new int[]{x, y});visited[x][y] = true;}}}int count = 0;for (int i = 1; i< rows-1; i++) {for (int j = 1; j < cols-1; j++) {if (grid[i][j] == 1 && visited[i][j] == false) {count++;}}}return count;}}
}

WFS

package graph.connected_land;import java.util.ArrayDeque;
import com.sun.jmx.remote.internal.ArrayQueue;/**/
public class Wfs {static class Solution {int [][] neighbors = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};public int numEnclaves(int[][] grid) {int rows = grid.length;int cols = grid[0].length;ArrayDeque<int[]> searched = new ArrayDeque<int[]>();boolean[][] visited = new boolean[rows][cols];for (int i = 0; i < rows; i++) {if (grid[i][0] == 1) {searched.offer(new int[]{i, 0});visited[i][0] = true;}if (grid[i][cols-1] == 1) {searched.offer(new int[]{i, cols-1});visited[i][cols-1] = true;}}for (int i=1; i < cols-1; i++ ) {if (grid[0][i] == 1) {searched.offer(new int[]{0, i});visited[0][i] = true;}if (grid[rows-1][i] == 1) {searched.offer(new int[]{rows-1, i});visited[rows-1][i] = true;}}while(!searched.isEmpty()) {int[] c = searched.poll();for (int[] neighbor : neighbors) {int x = c[0] + neighbor[0];int y = c[1] + neighbor[1];System.out.println("x " + x + "y " + y);if (x < 0 || x > rows-1 || y < 0 || y > cols-1 || visited[x][y] ){continue;}if (grid[x][y] == 1) {searched.offer(new int[]{x, y});visited[x][y] = true;}}}int count = 0;for (int i = 1; i< rows-1; i++) {for (int j = 1; j < cols-1; j++) {if (grid[i][j] == 1 && visited[i][j] == false) {count++;}}}return count;}}
}

测试数据

public static void main(String[] args) {int[][] grid = {{0,0,0,0},{1,0,1,0},{0,1,1,0},{0,0,0,0}};int[][] grid2 = {{0,1,1,0},{0,0,1,0},{0,0,1,0},{0,0,0,0}};int[][] grid3 = {{0,0,1,1,1,0,1,1,1,0,1},{1,1,1,1,0,1,0,1,1,0,0},{0,1,0,1,1,0,0,0,0,1,0},{1,0,1,1,1,1,1,0,0,0,1},{0,0,1,0,1,1,0,0,1,0,0},{1,0,0,1,1,1,0,0,0,1,1},{0,1,0,1,1,0,0,0,1,0,0},{0,1,1,0,1,0,1,1,1,0,0},{1,1,0,1,1,1,0,0,0,0,0},{1,0,1,1,0,0,0,1,0,0,1}};Wfs.Solution solution = new Wfs.Solution();System.out.println(solution.numEnclaves(grid3));}

链接

题目
https://leetcode-cn.com/problems/number-of-enclaves/

深度优先搜索与广度优先搜索的本质区别!
https://zhuanlan.zhihu.com/p/74472146

Java ArrayDeque
https://www.cainiaojc.com/java/java-arraydeque.html

深度优先搜索与广度优先搜索区别和案例相关推荐

  1. 八数码深度优先搜索_深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 关于搜索&遍历 对于搜索来说,我们绝大多数情况下处理的都是叫 "所谓的暴力搜索" ,或者是说比较简单朴素的搜索,也就是说你在搜索的时候没有任何所 ...

  2. 算法十——深度优先搜索和广度优先搜索

    文章出处:极客时间<数据结构和算法之美>-作者:王争.该系列文章是本人的学习笔记. 搜索算法 算法是作用于数据结构之上的.深度优先搜索.广度优先搜索是作用于图这种数据结构之上的.图上的搜索 ...

  3. 深度优先遍历和广度优先遍历_图与深度优先搜索和广度优先搜索

    什么是图? 图是一种复杂的非线性表结构.由若干给定的点一级任意两点间的连线所构成.图通常用来描述事物之间的特定关系, 代表的就是事物, 线就是事物之间所具有的关系.例如社交网络就是一种典型的图关系, ...

  4. 深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 ​ 在人工智能的运筹学的领域中求解与图相关的应用中,这两个算法被证明是非常有用的,而且,如需高效地研究图的基本性质,例如图的连通性以及图是否存在环,这些算法也是必不可少的. ...

  5. 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

    目录 一.图的遍历概念 二.深度优先搜索(DFS) (一)DFS算法步骤 1.邻接表DFS算法步骤 2.邻接矩阵DFS算法步骤 (二)深度优先生成树.森林 (三)DFS的空间复杂度和时间复杂度 三.广 ...

  6. 迷宫问题:深度优先搜索和广度优先搜索

    迷宫问题:深度优先搜索和广度优先搜索 1.深度优先搜索可以使用栈实现,栈顶元素为当前节点 2.当前节点搜索下一节点,判断节点是否走得通,如果走得通任意方向走一步,走不通一直弹出栈内元素,直到走得通 3 ...

  7. 学会二叉树不知道干啥?二叉树的深度优先搜索和广度优先搜索,我要打十个乃至二十个(打开你的LeetCode撸起来)学练并举

    目录 一. 图解二叉树的深度优先搜索 二. 二叉树的广度优先搜索  (层序遍历) 三. 打开LeetCode 撸起来 至此, 咱多少被刚刚的后序非递归搞得可能有点小晕晕的, 没事,层序简单呀....  ...

  8. 深度优先搜索和广度优先搜索的比较与分析

    一)深度优先搜索的特点是: (1)无论问题的内容和性质以及求解要求如何不同,它们的程序结构都是相同的,即都是深度优先算法(一)和深度优先算法(二)中描述的算法结构,不相同的仅仅是存储结点数据结构和产生 ...

  9. 深度优先搜索和广度优先搜索及典例分析(走迷宫问题(BFS)和棋盘问题(DFS))

    搜索算法在实际编程应用中起着举足轻重的作用,学会掌握搜索算法并熟练应用搜索算法来解决实际问题不得不说是一件相当COOL的事,所以我将深度搜索和广度搜索认真地做了详细的总结,与诸君共勉,也方便以后查阅复 ...

最新文章

  1. 探秘重编译(Recompilations)(1/2)
  2. 强化学习笔记:Actor-critic
  3. android适配器Adapter
  4. 微软雷德蒙德和伦敦地区掀起新一轮裁员 涉及数百人
  5. (二)spring cloud微服务分布式云架构-整合企业架构的技术点
  6. 八、Linux 常用 Shell 命令,控制台的快捷键以及 Shell 编程(中)
  7. Ubuntu Server安全Webserver搭建流程
  8. Linux命令-目录处理命令:mkdir
  9. C语言二维数组找出交集,【leetcode C语言实现】剑指 Offer 04. 二维数组中的查找...
  10. 【Django】毕设学习笔记(六)
  11. Android进程框架:线程通信的桥梁Handler
  12. gtx1050ti最稳定的驱动_【硬件资讯】持续霸榜经久不衰?四岁高龄的GTX1060仍为Steam最受欢迎显卡!...
  13. 多线程开发必须知道的概念
  14. 时区时钟插件html,World Clocks插件,世界时钟Chrome插件,轻松查看各国日期时间...
  15. python参考手册文字版_Python3.8标准库参考手册 中文完整pdf高清版
  16. 大名鼎鼎的挖掘鸡最新版本6.5
  17. 用手机怎么修改CAD图纸中的文字?
  18. BUUCTF Crypto [HDCTF2019]together wp
  19. 微信PC版应用双开,一台计算机两个微信号
  20. namespace MyProject 买来的二手车怎么查询是否发生过违章或交通事故,要查二手车的维修保养记录和出险记录?

热门文章

  1. python zip函数
  2. iphone开发小技巧汇总(1)
  3. 微信小程序体验版无法调用API接口,显示空白
  4. 论文笔记OHEM(Online Hard Example Mining)
  5. Strategy Analytics:假设禁令持续 华为全球手机出货量将同比下降24%
  6. Java中的泛型与异常机制
  7. [Python从零到壹] 四十八.图像增强及运算篇之形态学开运算、闭运算和梯度运算
  8. 客户为什么选怎外贸公司而不是工厂附赠外贸开发工具
  9. 微信小程序项目实例——备忘录
  10. c语言怎样同时接受两个按键,大家好,我现在想要实现同时按下两个按键在执行一个动作,不知怎么写了,求大神帮.......