「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」
题目
给你一个由 '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'
来源:力扣(LeetCode)leetcode-cn.com/problems/nu…
解题思路
-
上下左右相邻的为1格子组成陆地,那么这也是个连通性问题,可以用并查集来解决。
-
因为并查集内部存父节点的数据结构是一维数组,所以我们处理时要把二维的网格转成一维数组,公式为:
ind = (i, j) => i * m + j。 -
合并格子的时候只要合并上和左,因为右和下会在后面的循环中覆盖到。并且只合并值为1的格子。
-
合并完后,格子的值为1,并且并查集中这个格子的父节点是自己时,则是一个岛屿。循环找出所有这种情况去节点总数就是岛屿数。
代码实现
var numIslands = function (grid) {
const n = grid.length
const m = grid[0].length
//初始化一个数量为n*m的并查集
const u = new UnionSet(n * m)
//把二维数组转换为一维数组
const ind = (i, j) => i * m + j
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
//如果当前格子不等于1则不处理
if (grid[i][j] !== '1') continue
//如果上面的格子是1,则和当前格子合并
//当i等于0时说明是最上面一条边上,跳过
if (i > 0 && grid[i - 1][j] === '1') u.merge(ind(i, j), ind(i - 1, j))
//如果左边的格子是1,则和当前格子合并
//当j等于0时说明是最左边一条边上,跳过
if (j > 0 && grid[i][j - 1] === '1') u.merge(ind(i, j), ind(i, j - 1))
}
}
let ans = 0
//统计所有格子当中值为1,并且并查集中父节点等于自己的格子的个数,就是岛屿个数
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (grid[i][j] === '1' && u.get(ind(i, j)) === ind(i, j)) ans++
}
}
return ans
};
class UnionSet {
constructor(n) {
//初始化父节点数组,每个节点的父节点默认为自己
this.pa = new Array(n + 1).fill(0).map((item, index) => index)
//初始化每棵树的节点数
this.size = new Array(n + 1).fill(1)
}
get(x) {
//查找x的父节点,并且完成路径优化
//优化后,x的父节点指向所在树的根节点
return this.pa[x] = this.pa[x] === x ? x : this.get(this.pa[x])
}
merge(a, b) {
//找到a的根节点
const ra = this.get(a)
//找到b的根节点
const rb = this.get(b)
//如果a和b在一个集合中则不需要合并
if (ra === rb) return
//把节点总数小的集合合并到节点总数多的集合里
//更新节点总数多的集合为 a和b之和
if (this.size[ra] < this.size[rb]) {
this.pa[ra] = rb
this.size[rb] += this.size[ra]
} else {
this.pa[rb] = ra
this.size[ra] += this.size[rb]
}
}
}
如有错误欢迎指出,欢迎一起讨论!