Skip to content
本页目录

岛屿问题篇

在开始岛屿问题前先了解岛屿DFS模板一篇非常优秀且易懂的岛屿总结):

JavaScript
const template = grid => {
  const [row, col] = [grid.length, grid[0].length]

  const dfs = (i, j) => {
    // `base case`
    if (i < 0 || i >= row || j < 0 || j >= col) return  // 越界
    if (grid[i][j] !== 'legalValue') return  // 不符合要求
    // 标记(已遍历过)
    grid[i][j] = 'invalidValue'
    dfs(i + 1, j)
    dfs(i - 1, j)
    dfs(i, j - 1)
    dfs(i, j + 1)
  }

  /* 可能会有些预处理 */

  // 遍历
  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid[i][j] === 'legalValue') {
        // do something
        dfs(i, j)
      }
    }
  }
}

岛屿数量

200. 岛屿数量

JavaScript
const numIslands = grid => {
  const [row, col] = [grid.length, grid[0].length]
  let ret = 0

  const dfs = (i, j) => {
    if (i < 0 || i >= row || j < 0 || j >= col) return
    if (grid[i][j] !== '1') return
    grid[i][j] = '2'
    dfs(i + 1, j)
    dfs(i - 1, j)
    dfs(i, j - 1)
    dfs(i, j + 1)
  }

  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid[i][j] === '1') {
        ret++
        dfs(i, j)
      }
    }
  }
  return ret
}

时间复杂度:O(row*col);空间复杂度:O(row*col)

封闭岛屿数量

1254. 统计封闭岛屿的数目

JavaScript
const closedIsland = grid => {
  const [row, col] = [grid.length, grid[0].length]
  let ret = 0

  const dfs = (i, j) => {
    if (i < 0 || i >= row || j < 0 || j >= col) return
    if (grid[i][j] !== 0) return
    grid[i][j] = 2
    dfs(i + 1, j)
    dfs(i - 1, j)
    dfs(i, j - 1)
    dfs(i, j + 1)
  }

  // 逻辑上只需要额外先处理边界即可
  for (let i = 0; i < row; i++) {
    // 如果是第一行和最后一行,访问所有格子
    // 如果不是,只访问第一列和最后一列的格子
    const step = (i === 0 || i === row - 1) ? 1 : col - 1
    for (let j = 0; j < col; j += step) {
      dfs(i, j)
    }
  }

  for (let i = 1; i < row; i++) {
    for (let j = 1; j < col; j++) {
      if (grid[i][j] === 0) {
        ret++
        dfs(i, j)
      }
    }
  }
  return ret
}

时间复杂度:O(row*col);空间复杂度:O(row*col)

统计子岛屿

1905. 统计子岛屿

JavaScript
const countSubIslands = (grid1, grid2) => {
  const [row, col] = [grid1.length, grid1[0].length]
  let ret = 0

  const dfs = (i, j) => {
    if (i < 0 || i >= row || j < 0 || j >= col) return
    if (grid2[i][j] !== 1) return
    grid2[i][j] = 2
    dfs(i + 1, j)
    dfs(i - 1, j)
    dfs(i, j - 1)
    dfs(i, j + 1)
  }

  // 如果在grid1里是水域,在grid2是陆地,把它及邻近的陆地淹掉,排除掉不符合子岛屿的陆地
  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid1[i][j] == 0 && grid2[i][j] == 1) {
        dfs(i, j);
      }
    }
  }

  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid2[i][j] === 1) {
        ret++
        dfs(i, j)
      }
    }
  }
  return ret
}

时间复杂度:O(row*col);空间复杂度:O(row*col)

飞地的数量

1020. 飞地的数量

JavaScript
const closedIsland = grid => {
  const [row, col] = [grid.length, grid[0].length]
  let ret = 0
  if(row < 3 || col < 3) return ret

  const dfs = (i, j) => {
    if (i < 0 || i >= row || j < 0 || j >= col) return
    if (grid[i][j] !== 1) return
    grid[i][j] = 2
    dfs(i + 1, j)
    dfs(i - 1, j)
    dfs(i, j - 1)
    dfs(i, j + 1)
  }

  // 逻辑上只需要额外先处理边界即可
  for (let i = 0; i < row; i++) {
    // 如果是第一行和最后一行,访问所有格子
    // 如果不是,只访问第一列和最后一列的格子
    const step = (i === 0 || i === row - 1) ? 1 : col - 1
    for (let j = 0; j < col; j += step) {
      dfs(i, j)
    }
  }

  for (let i = 1; i < row; i++) {
    for (let j = 1; j < col; j++) {
      if (grid[i][j] === 1) {
        ret++
      }
    }
  }
  return ret
}

时间复杂度:O(row*col);空间复杂度:O(row*col)

岛屿的周长

463. 岛屿的周长

JavaScript
const islandPerimeter = grid => {
  const [row, col] = [grid.length, grid[0].length]

  const dfs = (i, j) => {
    // 边界处提供 一条有效边
    if (i < 0 || i >= row || j < 0 || j >= col) return 1
    // 海洋陆地相交处提供 一条有效边
    if (grid[i][j] === 0) return 1
    if (grid[i][j] !== 1) return 0
    grid[i][j] = 2
    return dfs(i + 1, j)
      + dfs(i - 1, j)
      + dfs(i, j - 1)
      + dfs(i, j + 1)
  }

  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid[i][j] === 1) {
        return dfs(i, j)
      }
    }
  }
}

时间复杂度:O(row*col);空间复杂度:O(row*col)

岛屿的最大面积

695. 岛屿的最大面积

JavaScript
const maxAreaOfIsland = grid => {
  const [row, col] = [grid.length, grid[0].length]
  let ret = 0

  const dfs = (i, j) => {
    if (i < 0 || i >= row || j < 0 || j >= col) return 0
    if (grid[i][j] !== 1) return 0
    grid[i][j] = 2
    return dfs(i + 1, j)
      + dfs(i - 1, j)
      + dfs(i, j - 1)
      + dfs(i, j + 1)
      + 1
  }

  // 求封闭岛屿最大面积
  // for(let i=0;i<row;i++) {
  //   const step= (i === 0 || i === row-1) ? 1 : col-1
  //   for(let j=0;j<col;j+=step) {
  //     dfs(i,j)
  //   }
  // }

  for (let i = 0; i < row; i++) {
    for (let j = 0; j < col; j++) {
      if (grid[i][j] === 1) {
        ret = Math.max(dfs(i, j), ret)
      }
    }
  }
  return ret
}

时间复杂度:O(row*col);空间复杂度:O(row*col)