【问题描述】

你现在手里有一份大小为 N x N 的『地图』(网格) grid,上面的每个『区域』(单元格)都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,你知道距离陆地区域最远的海洋区域是是哪一个吗?请返回该海洋区域到离它最近的陆地区域的距离。我们这里说的距离是『曼哈顿距离』( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个区域之间的距离是 |x0 - x1| + |y0 - y1| 。如果我们的地图上只有陆地或者海洋,请返回 -1。示例 1:
![image.png](https://upload-images.jianshu.io/upload_images/17025746-537539d18cf50a49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2提示:1 <= grid.length == grid[0].length <= 100
grid[i][j] 不是 0 就是 1

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

解释: 海洋区域 (1, 1) 和所有陆地区域之间的距离都达到最大,最大距离为 2。

【解答思路】

1. (威威的工程)BFS
  • 多个陆地起点入队列 ,弹出的同时向四周摸索,每次距离+1

时间复杂度:O(N^2) 空间复杂度:O(N^2)

 public int maxDistance(int[][] grid) {//方向向量int [][] directions = {{1,0},{-1,0},{0,1},{0,-1}};int N = grid.length;Queue<Integer> queue =  new LinkedList<>();for(int i= 0 ; i< N; i++){for(int j= 0 ; j < N; j++){if(grid[i][j]==1){queue.add(getIndex(i,j,N));}} }int size= queue.size();//全部是0或者全部是1 全海洋或全陆地if(size==0 || size == N*N){return -1;}int step = 0;while (!queue.isEmpty()){int  currentQueueSize = queue.size();for(int i=0 ;i<currentQueueSize;i++){Integer head = queue.poll();//巧妙一个数存放一个二维坐标int currentX =  head / N;int currentY =  head % N;for(int[] direction :directions){int newX = currentX+direction[0];int newY = currentY+direction[1];if(inArea(newX,newY,N) && grid[newX][newY]==0){//扩充海洋部分  赋值任何非0数 最后只关注最长路径grid[newX][newY] =1;queue.add(getIndex(newX,newY,N));}}}step++;}//最后一部没有扩散 但step++仍然执行 故最后结果需要-1return step-1;}/*** @param x    二维表格单元格横坐标* @param y    二维表格单元格纵坐标* @param cols 二维表格列数* @return*/private int getIndex(int x, int y, int cols) {return x * cols + y;}/*** @param x 二维表格单元格横坐标* @param y 二维表格单元格纵坐标* @param N 二维表格行数(列数)* @return 是否在二维表格有效范围内*/private boolean inArea(int x, int y, int N) {return 0 <= x && x < N && 0 <= y && y < N;}
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/yan-du-you-xian-bian-li-java-by-liweiwei1419/

​###### 2. (甜姨的刀法)BFS

  • 多个陆地起点入队列 ,弹出的同时向四周摸索,每次距离+1

时间复杂度:O(N^2) 空间复杂度:O(N^2)

 public int maxDistance(int[][] grid) {int[] dx = {0, 0, 1, -1};int[] dy = {1, -1, 0, 0};Queue<int[]> queue = new ArrayDeque<>();int m = grid.length, n = grid[0].length;// 先把所有的陆地都入队。for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == 1) {queue.offer(new int[] {i, j});}}}// 从各个陆地开始,一圈一圈的遍历海洋,最后遍历到的海洋就是离陆地最远的海洋。boolean hasOcean = false;int[] point = null;while (!queue.isEmpty()) {point = queue.poll();int x = point[0], y = point[1];// 取出队列的元素,将其四周的海洋入队。for (int i = 0; i < 4; i++) {int newX = x + dx[i];int newY = y + dy[i];if (newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0) {continue;}grid[newX][newY] = grid[x][y] + 1; // 这里我直接修改了原数组,因此就不需要额外的数组来标志是否访问hasOcean = true;queue.offer(new int[] {newX, newY});}}// 没有陆地或者没有海洋,返回-1。if (point == null || !hasOcean) {return -1;}// 返回最后一次遍历到的海洋的距离。return grid[point[0]][point[1]] - 1;}作者:sweetiee
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/jian-dan-java-miao-dong-tu-de-bfs-by-sweetiee/

【总结】

1. BFS
  • 如果题目要求返回的结果和距离相关,需要在 while 循环内部一下子把当前列表的所有元素都依次取出来,这种「一下子」操作的次数就是我们需要的距离;
  • 如果一个单元格被添加到队列以后,需要马上将它标记为已经访问(根据情况,可以直接在原始输入数组上修改,也可以使用一个布尔数组 visited 进行标记),否则很可能会出现死循环
2.树与无向图的BFS
  • 树只有一个root ,无向图有多个源点
  • 树是有向的 不需要标注是否访问过,无向图需要标记是否访问过且需要在入队之前设置为已访问(防止节点重复入队)!
3. 二维表格上编码代码的常用技巧
  • 设置方向数组
int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
  • 设置是否越界的判断函数 inArea()
  • 根据情况,使用二维坐标和一维坐标相互转换的操作,因为二维坐标传入队列的时候,需要封装成数组,创建和销毁数组有一定性能消耗
private int getIndex(int x, int y, int cols) {return x * cols + y;}

[Leedcode][JAVA][第1162题][BFS]相关推荐

  1. [Leedcode][JAVA][第105题][从前序与中序遍历序列构造二叉树][栈][递归][二叉树]

    [问题描述][中等] 根据一棵树的前序遍历与中序遍历构造二叉树.注意: 你可以假设树中没有重复的元素.例如,给出前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = ...

  2. [Leedcode][JAVA][第470题][Ran7()实现Rand10()]

    [问题描述][Leedcode][JAVA][第470题][Ran7()实现Rand10()] 已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 ...

  3. [Leedcode][JAVA][第45题][跳跃游戏 II][贪心算法]

    [问题描述][Leedcode][JAVA][第45题][跳跃游戏 II] 输入: [2,3,1,1,4] 输出: 2 解释: 跳到最后一个位置的最小跳跃数是 2.从下标为 0 跳到下标为 1 的位置 ...

  4. [Leedcode][JAVA][第210 题][课程表 II][拓扑排序][BFS][DFS][有向图]

    [问题描述][第210 题][课程表 II][中等] 现在你总共有 n 门课需要选,记为 0 到 n-1.在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用 ...

  5. [Leedcode][JAVA][第102题][二叉树的层序遍历][递归][迭代][BFS]

    [问题描述][第102题][二叉树的层序遍历][中等] 给你一个二叉树,请你返回其按 层序遍历 得到的节点值. (即逐层地,从左到右访问所有节点).示例: 二叉树:[3,9,20,null,null, ...

  6. [Leedcode][JAVA][第22题括号生成][DFS][BFS][动态规划]

    [问题描述]22. 括号生成 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合. 示例:输入:n = 3 输出:["((()))",&q ...

  7. [Leedcode][JAVA][第200题][岛屿数量][DFS][BFS][并查集]

    [问题描述] 第200题 岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量.岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成 ...

  8. [剑指offer]面试题第[37]题[Leedcode][JAVA][第297题][二叉树列的序列化与反序列化][递归][BFS]

    [问题描述][中等] 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据.请设 ...

  9. [剑指offer]面试题第[68-1]题[Leedcode][JAVA][第235题][二叉搜索树的最近公共祖先][递归][BFS]

    [问题描述][第235题][二叉搜索树的最近公共祖先][简单] 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先.百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p. ...

最新文章

  1. 拯救莫莉斯[GDOI2014]
  2. IOS学习笔记(九)之UIAlertView(警告视图)和UIActionSheet(操作表视图)基本概念和使用方法...
  3. python将数据写入excel_【Python】将数据库中的数据查询出来自动写入excel文档
  4. 数据库索引失效的一些场景
  5. 汇编语言王爽实验17
  6. QT D:\搜狗输入法\SogouInput\Components\ 13:53:42: 程序异常结束。 13:53:42: T
  7. 农产品加工进销存单_实用必看!手把手教你制作进销存出入库表格
  8. 手机投屏到电脑完美教程,安卓和苹果用户均可使用
  9. python爬取中央气象台台风网当前台风实况和预报数据
  10. mybatis中查询oracle数据库date类型的时间没有时分秒
  11. 查询Linux中CPU的核数
  12. estimate 和 estimation
  13. 有什么软件可以搜JAVA题答案_可以搜简答题答案及解析的软件app或者公众号有吗?...
  14. 微信小程序最新获取头像和昵称的方法 直接用!
  15. Java实现字母去重
  16. 日历javascript代码
  17. Vue 使用图表插件 -- Echarts
  18. C 三个学生四门成绩,求成绩总和与平均值
  19. 小乌龟怎么拉取最新代码_TotoiseSVN(中文名:小乌龟)使用教程
  20. 代码格式调整 Astyle 基本使用

热门文章

  1. MVC5中利用NOPI导出EXCLE
  2. 2016年5月28日(项目任务)
  3. Mysql递归查询,无限级上下级菜单
  4. 【卡法电子商务】-常用手机屏幕尺寸 ★★★★★
  5. Web中的鼠标自动移动
  6. 单片机shell命令_MCU调试大法:使用串口实现简单shell功能
  7. JavaScript之继承模式,命名空间,对象枚举
  8. 小程序真机测试「启动参数」解析出错问题
  9. 考研计算机专业课统考吗,【计算机考研】你了解计算机统考408吗?
  10. c语言编写期末考试成绩,C语言期末考试卷(A卷含答案).doc