这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
144. 岛屿数量 (number-of-islands)
标签
- 染色
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
给你一个由 '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
基本思路
其实这个问题就是典型的染色问题
我们其实就是遍历所有位置,先判断是否是陆地,如果是陆地就往4个方向探索并把陆地沉掉,附近连着的陆地都被沉掉了,计算数量就可以加 1。思路还是比较简单的,就是染色方式可以有多种。
编码步骤:
- 我们要计算岛屿数量,需要有个
count
变量 - 开始遍历所有格子,发现
0
,则不做操作 - 如果是
1
,count++
, 表明这是陆地,那么这块陆地有多大,则可以用DFS/BFS
继续探索它的上下左右,发现是陆地就染上色,最后都探索到边界,说明这个岛都被染色了 然后直接把所有岛沉了,(染色格子从 1 => 0
),继续向下遍历。 - 到最后
count
是算出来了 ,格子里都变成了0
对 DFS 和 BFS 不熟悉 可以看这篇 DFS/BFS
写法实现
DFS
var numIslands = function(grid) {
let count = 0, rows = grid.length, cols = grid[0].length
// 四个方向的移动配置
const direction = [[0, 1], [0, -1], [1, 0], [-1, 0]]
const dfs = (i, j) => {
for ([dx, dy] of direction) {
// 走过步数后的坐标
let nowI = i + dx, nowJ = j + dy
// 不超过边界的,且是 1的 染色置 0
if (nowI >= 0 && nowJ >= 0 && nowI < rows && nowJ < cols && grid[nowI][nowJ] === '1') {
grid[nowI][nowJ] = '0'
// 继续递归查找
dfs(nowI, nowJ)
}
}
}
// 开始遍历
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (grid[i][j] === '1') {
count++
// 染色沉岛
dfs(i, j)
}
}
}
return count
};
let grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
console.log(numIslands(grid))
BFS
类似的,用广度优先做染色,类比二叉树层序遍历
你会有新的收获。
var numIslands = function(grid) {
let count = 0, rows = grid.length, cols = grid[0].length
const direction = [[0, 1], [0, -1], [1, 0], [-1, 0]]
// 做 BFS 需要一个辅助队列 queue
let queue = []
const bfs = () => {
while (queue.length > 0) {
let [i, j] = queue.shift()
for ([dx, dy] of direction) {
let [nowI, nowJ] = [i + dx, j + dy]
if (nowI >= 0 && nowJ >= 0 && nowI < rows && nowJ < cols && grid[nowI][nowJ] === '1') {
grid[nowI][nowJ] = '0'
// 推入下一个种子节点 (类似层序遍历的下一层)
queue.push([nowI, nowJ])
}
}
}
}
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (grid[i][j] === '1') {
count++
// 染色沉岛
grid[i][j] = '0'
// 推入一个种子做 bfs 搜索
queue.push([i, j])
bfs()
}
}
}
return count
}
let grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
console.log(numIslands(grid))
拓展
还有一种查并集的方式,比较复杂,建议先了解查并集是什么再看解决方式 岛屿问题
另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友
Or 搜索我的微信号infinity_9368
,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文
,验证消息请发给我
presious tower shock the rever monster
,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧