19. 岛屿数量【LC200】

119 阅读1分钟

题目:

给你一个由 '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
 

提示:

m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 '0' 或 '1'

核心思路: 循环网格,深度优先遍历每个坐标的四周,注意坐标不要越界,遇到陆地加1,并沉没四周的陆地,这样就不会重复计算. 关键点,从头按顺序遍历网格,会向后修改,这其中默认依赖数据处理顺序了,顺序遍历陆地点,DFS找到当前所属陆地,并下沉当前陆地,再继续遍历

尤其要注意递归的收敛条件,因为存在向四周检索,i、j都存在加减的情况,递减要找左边界,递增要找右边界。按

解:

const numIsLand = (grids) => {
  let count = 0;
  for (let i = 0; i < grids.length; i++) {
    for (let j = 0; j < grids[0].length; j++) {
      if (grids[i][j] === '1') { 
      // 按顺序遍历陆地点,DFS找到当前所属陆地,并下沉当前陆地,再继续遍历
        count++;
        turnZero(grids, i, j)
      }
    }
  }
  return count;
}

function turnZero(arr, i, j) {
  // DFS 下沉当前节点所属陆地(相邻四个节点)
  if (i < 0 || j < 0 || i >= arr.length || j >= arr[0].length || arr[i][j] === '0') return;
  arr[i][j] = '0';
  turnZero(arr, i, j + 1)
  turnZero(arr, i, j - 1)
  turnZero(arr, i + 1, j)
  turnZero(arr, i - 1, j)
}

小窍门: 总结了一下,存在一套模板,来解决岛屿类问题:

// 按顺序遍历陆地点,DFS找到当前所属陆地,并下沉当前陆地,再继续遍历
const numIsLand = (grids) => {
  for (let i = 0; i < grids.length; i++) {
    for (let j = 0; j < grids[0].length; j++) {
     if (grids[i][j] === '1') { 
         xxxxxxxxxxx
          dfs(grids, i, j)
      }
    }
  }
  return xxxxxxxx;
}

function dfs(arr, i, j) {
  // DFS 下沉当前节点所属陆地(相邻四个节点)
  if (i < 0 || j < 0 || i >= arr.length || j >= arr[0].length || arr[i][j] === '0' || arr[i][j] === 0) return;
  // 此处根据题目具体需求进行操作
  arr[i][j] = '0';
  // 用于访问当前节点的上下左右的四个节点,进行递归调用
  dfs(arr, i, j + 1)
  dfs(arr, i, j - 1)
  dfs(arr, i + 1, j)
  dfs(arr, i - 1, j)
}

———— 前端、Javascript实现、算法、刷题、leetcode