LeetCode算法学习之--Graph--岛屿数量

770 阅读1分钟

大家好今天给大家分享下一道 LeetCode 中等难度 的题目200. 岛屿数量

题目

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

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

输入:grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
输出:3

分析

1.只能水平方向访问 或者垂直方法访问

2.1与1之间相连,0不能访问

3.返回数字

解法

1.dfs

2.bfs

解法一:DFS

思路
1.因为是二维解决所以通过两层遍历每个节点
2.如果碰到'1'代表可以走,所以进行dfs遍历,同时代表了遇到了一个岛屿 count++
3.dfs 深度优先遍历
    1.首先判断是否在矩阵中 isGrid(i,j)
    2.在判断是否是访问过的 set.has(i+'_'+j)(因为访问的时候可能会访问重复的节点)
    3.访问过的节点加入set中
    4.是个方法访问周边的节点
*/

var numIslands = function (grid) {
  // 添加set 防止重复访问
  const set = new Set();
  let res = 0;

  for (let i = 0; i < grid.length; i++) {
    for (let j = 0; j < grid[0].length; j++) {
      //   只有为‘1’并且set中不存在的值才能进入dfs访问
      if (grid[i][j] === "1" && !set.has(i + "_" + j)) {
        visitGridElementDfs(grid, i, j);
        res++;
      }
    }
  }

  return res;

  // 判断是否在矩阵中
  function inGrid(i, j) {
    return i > -1 && i < grid.length && j > -1 && j < grid[0].length;
  }

  function visitGridElementDfs(grid, i, j) {
    // 不在矩阵中返回
    if (!inGrid(i, j)) {
      return;
    }
    // 遇到‘0’返回
    if (grid[i][j] === "0") {
      return;
    }
    // 遇到访问过的节点返回
    if (set.has(i + "_" + j)) {
      return;
    }

    set.add(i + "_" + j);

    // 向上访问
    visitGridElementDfs(grid, i + 1, j);
    // 向下访问
    visitGridElementDfs(grid, i - 1, j);
    // 向左边访问
    visitGridElementDfs(grid, i, j + 1);
    // 向右边访问
    visitGridElementDfs(grid, i, j - 1);
  }
};

/* 复杂度
时间 O(MN) M为行数 N为列数, 
空间 O(MN)
*/

解法二:BFS

思路
1.因为是二维解决所以通过两层遍历每个节点
2.如果碰到'1'代表可以走,所以进行dfs遍历,同时代表了遇到了一个岛屿 count++
3.bfs 广度优先遍历
    1.首先把起点放入一个队列中
    2.取出队列首部元素,然后判断
     1.是否在 矩阵中 
     2.是否遇到了‘03.是否访问过
    3.如果上述条件都不满足,则把这个元素各个方法的元素都放入队列中
*/

var numIslands = function (grid) {
  const seen = new Set();
  let count = 0;
  for (let i = 0; i < grid.length; i++) {
    for (let j = 0; j < grid[0].length; j++) {
      //   只有为‘1’并且set中不存在的值才能进入dfs访问
      if (grid[i][j] === "1" && !seen.has(i + "_" + j)) {
        visitGridElementBfs(grid, i, j);
        count++;
      }
    }
  }

  return count;

  // 判断是否在矩阵中
  function inGrid(i, j) {
    return i > -1 && i < grid.length && j > -1 && j < grid[0].length;
  }

  function visitGridElementBfs(grid, i, j) {
    const list = [];
    list.push([i, j]);

    while (list.length) {
      const cur = list.shift();
      (i = cur[0]), (j = cur[1]);

      if (!inGrid(i, j)) continue;
      if (grid[i][j] === "0") continue;
      if (seen.has(i + "_" + j)) continue;

      seen.add(i + "_" + j);
      list.push([i + 1, j]);
      list.push([i - 1, j]);
      list.push([i, j + 1]);
      list.push([i, j - 1]);
    }
  }
};

/* 复杂度
时间 O(MN) M为行数 N为列数
空间 O(MN)
*/

总结

这道题考察的是Graph的应用,如何使用DFS 来BFS 遍历节点

大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢

大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持

文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com