[LeetCode] 1020. Number of Enclaves 飞地的数量
Given a 2D array A
, each cell is 0 (representing sea) or 1 (representing land)
A move consists of walking from one land square 4-directionally to another land square, or off the boundary of the grid.
Return the number of land squares in the grid for which we cannot walk off the boundary of the grid in any number of moves.
Example 1:
Input: [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
Output: 3
Explanation:
There are three 1s that are enclosed by 0s, and one 1 that isn't enclosed because its on the boundary.
Example 2:
Input: [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
Output: 0
Explanation:
All 1s are either on the boundary or can reach the boundary.
Note:
1 <= A.length <= 500
1 <= A[i].length <= 500
0 <= A[i][j] <= 1
- All rows have the same size.
这道题给了一个只有0和1的二维数组A,其中0表示海洋,1表示陆地,每次只能从一块陆地走到和其相连的另一块陆地上,问有多少块陆地可以不用走到边界上。其实这道题就是让找出被0完全包围的1的个数,反过来想,如果有1在边界上,那么和其相连的所有1都是不符合题意的,所以只要以边界上的1为起点,遍历所有和其相连的1,并且标记,则剩下的1一定就是被0完全包围的。遍历的方法可以用 BFS 或者 DFS,先来看 BFS 的解法,使用一个队列 queue,遍历数组A,现将所有1的个数累加到结果 res,然后将边界上的1的坐标加入队列中。然后开始 while 循环,去除队首元素,若越界了,或者对应的值不为1,直接跳过。否则标记当前位置值为0,并且 res 自减1,然后将周围四个位置都排入队列中,最后返回结果 res 即可,参见代码如下:
解法一:
class Solution {
public:
int numEnclaves(vector<vector<int>>& A) {
int res = 0, m = A.size(), n = A[0].size();
queue<vector<int>> q;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
res += A[i][j];
if (i * j == 0 || i == m - 1 || j == n - 1) q.push({i, j});
}
}
while (!q.empty()) {
int x = q.front()[0], y = q.front()[1]; q.pop();
if (x < 0 || x >= m || y < 0 || y >= n || A[x][y] != 1) continue;
A[x][y] = 0;
--res;
q.push({x + 1, y});
q.push({x - 1, y});
q.push({x, y + 1});
q.push({x, y - 1});
}
return res;
}
};
再来看递归的写法,其实并没有啥不同,对于每个边界的1,都调用递归函数,并将所有相连的1标记为0,最后再遍历一遍数组A,统计剩下的1的个数返回即可,参见代码如下:
解法二:
class Solution {
public:
int numEnclaves(vector<vector<int>>& A) {
int res = 0, m = A.size(), n = A[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i * j == 0 || i == m - 1 || j == n - 1) helper(A, i, j);
}
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (A[i][j] == 1) ++res;
}
}
return res;
}
void helper(vector<vector<int>>& A, int i, int j) {
if (i < 0 || i >= A.size() || j < 0 || j >= A[0].size() || A[i][j] != 1) return;
A[i][j] = 0;
helper(A, i + 1, j);
helper(A, i - 1, j);
helper(A, i, j + 1);
helper(A, i, j - 1);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1020
参考资料:
https://leetcode.com/problems/number-of-enclaves/
https://leetcode.com/problems/number-of-enclaves/discuss/266168/Easy-Java-DFS-6ms-solution
https://leetcode.com/problems/number-of-enclaves/discuss/265555/C%2B%2B-with-picture-DFS-and-BFS