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

267 阅读2分钟

岛屿问题

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

思路:
深度优先遍历:循环二维数组,当遇到1时,把该值置为2,并把该值前后左右都进行递归判断,例如都先判断右侧是否为1,直到右侧为0退出,再到下侧,左侧,上侧,这就是深度优先搜索

function numIslands(grid) {
  let num = 0;
  let rows = grid.length;
  for(let i = 0; i < rows; i++) {
      let cols = grid[i].length;
      for(let j = 0; j < cols; j ++) {
        if(grid[i][j] == 1) {
          dfs(grid, i, j, rows, cols);
          num ++
        }
      }
  }
}
// rows和cols的作用是判断是否越界,当i > rows时就越界了,例如示例中i = 5,并没有第5行
function dfs(grid, i, j, rows, cols) {
    // 递归终止条件
    if(i < 0 || i > rows || j < 0 || j > cols || grid[i][j] != 1) return
    
    grid[i][j] = 2
    dfs(grid, i + 1, j, rows, cols)
    dfs(grid, i - 1, j, rows, cols)
    dfs(grid, i, j + 1, rows, cols)
    dfs(grid, i, j - 1, rows, cols)
}

image.png

广度优先搜索
思路: 循环二维数组,当遇到值为1时,把该值对应的[i, j]放进队列中,并把该值置为2,再对队列进行循环,从队列取出一个[i, j],判断该值的上下左右是否为1,为1就放进队尾。直到队列为空,当前岛屿就找完了,继续寻找下一个岛屿

function numIslands(grid) {
  let queue = []; // BFS的队列
  let num = 0; // 岛屿数
  let rows = grid.length - 1; // 二维数组长度,判断越界
  for (let i = 0; i < grid.length; i++) {
    let cols = grid[i].length - 1; // 子数组长度,判断越界 
    for (let j = 0; j < grid[i].length; j++) {
      if (grid[i][j] == 1) {
        queue.push([i, j]); // 为1放进队列
        grid[i][j] = 2; // 要先置为2
        while (queue.length > 0) {
          let [x, y] = queue.shift();
          if (x - 1 >= 0 && grid[x - 1][y] == 1) {
            queue.push([x - 1, y]);
            grid[x - 1][y] = 2; // 要先置为2,否则会重复添加相同的节点
          }
          if (x + 1 <= rows && grid[x + 1][y] == 1) {
            queue.push([x + 1, y]);
            grid[x + 1][y] = 2;
          }

          if (y + 1 <= cols && grid[x][y + 1] == 1) {
            queue.push([x, y + 1]);
            grid[x][y + 1] = 2;
          }
          if (y - 1 >= 0 && grid[x][y - 1] == 1) {
            queue.push([x, y - 1]);
            grid[x][y - 1] = 2;
          }
        }
        num++;
      }
    }
  }
  return num;
}

image.png 广度优先算法不是原地算法,需要一个队列来存储,所以内存消耗较大,深度优先就不需要了


时间复杂度: O(MN),每个值都需遍历一次
空间复杂度: O(MN),有MN个函数上下文保存在栈中