「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」
前言
今日的题目为中等,最开始以为是和之前一道题一样的思路,但是后来发现并不好做,最后转变了一下思路就变得很简单,有时候碰到了类似的题目如果发现不太对劲就要及时转变思路,换一个方向思考可能就会简单很多。
每日一题
今天的每日一题 1020. 飞地的数量,难度为中等
-
给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。
-
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。
-
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。
示例 1:
输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。
示例 2:
输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。
提示:
- m == grid.length
- n == grid[i].length
- 1 <= m, n <= 500
- grid[i][j] 的值为 0 或 1
题解
深度优先遍历
这道题和前几天做的黄金矿工有着异曲同工之妙,只是这道题的求法和黄金矿工是相反的。
黄金矿工的思维是去遍历每一个单元格,当这个格子周围存在不为零的数就向前进,最后回去对比每一条不同路线的结果。
今天这道题利用相反的思维会更加的简便,我们可以从最外面一圈往里面遍历,存在值为1的格子就前进,并且把经过的格子值都变成0,最后只需要去统计值为1的格子的数量就可以了。
-
如上图 示例2 的例子当中,我们先去遍历周围一圈红色框,找到值为1的单元格。
-
从这个单元格开始,四周要是存在值为1的单元格就往前遍历,并且当前单元格值置为0。
- 知道遍历完周围一圈值为1的单元格,然后就可以去统计剩余值为1的单元格,就是题目需要的答案。
/**
* @param {number[][]} grid
* @return {number}
*/
var numEnclaves = function (grid) {
let m = grid.length;
let n = grid[0].length;
let ans = 0;
for (let i = 0; i < m; i++) {
dfs(grid, i, 0);
dfs(grid, i, n - 1);
}
for (let j = 0; j < n; j++) {
dfs(grid, 0, j);
dfs(grid, m - 1, j);
}
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j] === 1) {
ans++;
}
}
}
return ans;
};
var dfs = function (grid, x, y) {
if (
x < 0 ||
y < 0 ||
x >= grid.length ||
y >= grid[0].length ||
grid[x][y] === 0
) {
return;
}
grid[x][y] = 0;
dfs(grid, x + 1, y);
dfs(grid, x - 1, y);
dfs(grid, x, y + 1);
dfs(grid, x, y - 1);
};