1020. 飞地的数量(2022-2-12)
给你一个大小为 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
解题思路
不管是dfs还是bfs都可以,本文选择bfs;关于dfs的题可以看我之前的blog黄金矿工
另外一道bfs的题地图中的最高点
本题的一个关键点在于,起点的选择,是矩形的四条边上的陆地。因此我们在记录所有陆地的同时,将位于边上的陆地加入起点队列。
起点队列有了之后就是标准的bfs。
var numEnclaves = function (grid) {
//多源bfs
let queue = [],
m = grid.length,
n = grid[0].length;
let count = 0, //陆地数量
ret = []; //非飞地数量
let direction = [
[0, 1],
[0, -1],
[1, 0],
[-1, 0],
];
grid.forEach((row, i) => {
row.forEach((v, j) => {
if (v == 1) {
if (i == 0 || j == 0 || i == m - 1 || j == n - 1) {
queue.push([i, j]);
grid[i][j] = 0;
}
count++;
}
});
});
// 标准的bfs
while (queue.length)
let start = queue.shift()
ret.push(start)
for (let [_x, _y] of direction) {
let x = start[0] + _x;
let y = start[1] + _y;
if (x > 0 && y > 0 && (x < m) & (y < n) && grid[x][y] == 1) {
queue.push([x, y]);
grid[x][y] = 0;
}
}
}
return count - ret.length;
};