【DFS和并查集】 岛屿数量 [Go语言]

322 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

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

思路

这道题我们可以用二维表的dfs,遍历到一个就让他的上下左右都变成0,再次遍历的时候,就不再记录这个岛屿的数量了。

AC Code

DFS 做法

func numIslands(grid [][]byte) int {
    var res int
    for i:=0; i<len(grid); i++ {
        for j:=0; j<len(grid[0]); j++ {
            if grid[i][j] == '1' {
(1)                res++
(2)                dfsArea(grid,i,j)
            }
        }
    }
    return res
}

func dfsArea(grid [][]byte,r,c int){
    h, w := len(grid), len(grid[0])
(3)    if r < 0 || r >= h || c < 0 || c >= w {
        return
    }
(4)    if grid[r][c]=='0'{
        return
    }
(5)    grid[r][c]='0'
    dfsArea(grid,r-1,c)
    dfsArea(grid,r+1,c)
    dfsArea(grid,r,c-1)
    dfsArea(grid,r,c+1)
}
  • (1) 当碰到1的时候就可以直接进行一次记录
  • (2) 然后从这个1的位置开始dfs,知道遍历完上下左右都是0位置
  • (3) 这里的边界条件是我们上下左右进行运算的时候要合理,不能超过这里的上下左右的边界
  • (4) 如果这个r和c等于0也可以直接返回了。
  • (5) 将遍历到的岛屿的1全部变成0,再继续进行一次遍历。

并查集做法

我们知道这个并查集是建立起来的即可!只要是碰到了导入就放入到查并集中,然后再查询这个查并集即可

func numIslands(grid [][]byte) int {
   m := len(grid)
   n := len(grid[0])
   ans := 0
(1)   dx := []int{-1, 0, 0, 1}
   dy := []int{0, -1, 1, 0}
(2)   fa := make([]int, m*n+1)
(3)   for i := 0; i <= m*n; i++ {
      fa[i] = i
   }
(4)   for i := 0; i < m; i++ {
      for j := 0; j < n; j++ {
(5)         if grid[i][j] == '0' {
            continue
         }
         for k := 0; k < 4; k++ {
            nx := i + dx[k]
            ny := j + dy[k]
(6)            if nx >= m || ny >= n || nx < 0 || ny < 0 {
               continue
(7)            } else if grid[nx][ny] == '1' {
               unionSet(fa, nums(n, i, j), nums(n, nx, ny))
            }
         }
      }
   }
(8)   for i := 0; i < m; i++ {
          for j := 0; j < n; j++ {
(9)         if grid[i][j] == '1' && Find(fa, nums(n, i, j)) == nums(n, i, j) {
            ans++
         }
      }
   }
   return ans
}
  • (1) 方向数组
  • (2) 初始化并查集
  • (3) 二维索引转一维
  • (4) 循环网格
  • (5) 如果碰到水则continue
  • (6) 到了边界continue
  • (7) 如果相邻是1,则加入并查集 uninonset
  • (8) 最后查找并查集根的个数即可
  • (9) 如果字符为1,且根是自己本身,说明找到一个根,ans++