Leet-Code 飞地数量
问题描述:
给出一个二维数组 A
,每个单元格为 0(代表海)或 1(代表陆地)。
移动是指在陆地上从一个地方走到另一个地方(朝四个方向之一)或离开网格的边界。
返回网格中无法在任意次数的移动中离开网格边界的陆地单元格的数量。
输入输出实例:
输入:[[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] 输出:3 解释: 有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。
分析:
题目要求找出所有无法飞出的点,那么能飞出飞地的点具体是什么呢?
首先可以明确,处在边界的点可以直接飞出,那么处在中间的点呢?
答案是,必须在四个方向上与边界点有通路。
以此,我们直接从边界出发,把所有能飞出的点遍历到(DFS),并赋值为0,剩下的因为压根儿没法和边界相通,所以肯定是无法飞出的点。
//1020. 飞地的数量
let dx = [-1, 0, 1, 0];
let dy = [0, -1, 0, 1];
var numEnclaves = function(A) {
let res = 0;
let leni = A.length; //行数
let lenj = A[0].length;//列数
//从边界捕捉所有能飞出边界的点,遍历完剩下的都不能飞出去。
for (let j = 0; j < lenj; j++) { //遍历上边界
if (A[0][j] == 1) {
dfs(A, 0, j, leni, lenj);
}
}
for (let i = 1; i < leni-1; i++) { //遍历左边界
if (A[i][0] == 1) {
dfs(A, i, 0, leni, lenj);
}
}
for (let i = 1; i < leni-1; i++) { //遍历右边界
if (A[i][lenj-1] == 1) {
dfs(A, i, lenj - 1, leni, lenj);
}
}
for (let j = 0; j < lenj; j++) { //遍历下边界
if (A[leni-1][j] == 1) {
dfs(A, leni - 1, j, leni, lenj);
}
}
//计算剩下的1,还有多少即可
for (let index = 0; index < leni; index++) {
A[index].forEach((val) => {
res += val;
});
}
return res;
};
function dfs(A,i,j,leni,lenj) {
A[i][j] = 0;
for (let index = 0; index < 4; index++) {
let x = i + dx[index];//行
let y = j + dy[index];//列
if (x >= 0 && x < leni && y >= 0 && y < lenj && A[x][y]==1) {
dfs(A, x, y, leni, lenj);
}
}
return;
}