大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。
题目
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
示例 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.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]的值为'0'或'1'
思路
- 两层
for循环,去遍历我们矩阵中的每一个元素,如果遍历到的节点值为"1",那么进行消除; - 消除规则是这样子的,像我们玩扫雷一样,中间一个是
1了那把跟它紧挨着的几个元素全都改成0; - 但是这道题目我们要进行连续的消除,所以我们要对下一个元素做同样的操作,也就形成了递归问题;
- 那么递归的条件是什么呢?就是直到超出边界或者当前元素本身就是
0这两种情况; - 所以我们只需要在递归时判断是否达到了这两种情况,如果是就不往下执行,如果不是就消除它四周的元素。
dfs + 递归
/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function(grid) {
const m = grid.length, n = grid[0].length;
// 快乐消除
function dfs(grid, i, j) {
// 判断是否超出边界
if (i < 0 || j < 0 || i >= m || j >= n || grid[i][j] === "0") {
return;
}
grid[i][j] = "0";
// 朝四周扩散
dfs(grid, i - 1, j);
dfs(grid, i + 1, j);
dfs(grid, i, j - 1);
dfs(grid, i, j + 1);
}
let result = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === "1") {
dfs(grid, i, j);
result++;
}
}
}
return result;
};
bfs + 迭代
迭代的思路跟递归基本一直,只不过是把四周的元素全部放到待操作的数组里面,一个一个拿出来,这样子其实每一轮只需要存储一行或者一列元素即可,可以省下一定的空间。当然,如果这道题目要优化,可以把判断操作放到push的代码之前,如果溢出边界则不push,这样子可以达到最高性能,不过我为了方便理解就用最精简的代码来实现。
/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function(grid) {
const m = grid.length, n = grid[0].length;
// 快乐消除
function bfs(grid, queue) {
while (queue.length) {
let { i, j } = queue.shift();
// 判断是否超出边界
if (!(i < 0 || j < 0 || i >= m || j >= n || grid[i][j] === "0")) {
grid[i][j] = "0";
queue.push({ i: i - 1, j });
queue.push({ i: i + 1, j });
queue.push({ i, j: j - 1 });
queue.push({ i, j: j + 1 });
}
}
}
let result = 0;
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === "1") {
bfs(grid, [{ i, j }]);
result++;
}
}
}
return result;
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。