这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战
题目描述
给你一个大小为 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 都在边界上或可以到达边界。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-enclaves
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路分析
- 今天的算法题目是岛屿处理问题,解决岛屿问题,我们一般常常采用DFS,BFS,并查集等思路求解。
- 这个题目有一个重要描述是 飞地。什么是飞地呢?飞地,一种特殊的人文地理现象,指隶属于某一行政区管辖但不与本区毗连的土地。如果某一行政主体拥有一块飞地,那么它无法取道自己的行政区域到达该地,只能“飞”过其他行政主体的属地,才能到达自己的飞地。简单理解就是没有关联的位置。
- 利用这个条件,参考官方题解,我们可以从外到内便利每一个岛屿,使用DFS,或者BFS 等方法对于能访问到的岛屿进行标记。然后在遍历整个岛屿的内部,找到访问不到的岛屿,即为飞地。具体实现代码如下,供参考。
通过代码
class Solution {
int[] dx = new int[]{-1, 1, 0, 0};
int[] dy = new int[]{0, 0, 1, -1};
int m = 0;
int n = 0;
public int numEnclaves(int[][] grid) {
m = grid.length;
n = grid[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
dfs(i, 0, grid, visited);
dfs(i, n - 1, grid, visited);
}
for (int j = 0; j < n; j++) {
dfs(0, j, grid, visited);
dfs(m - 1, j, grid, visited);
}
int ans = 0;
for (int i = 1; i < m - 1; i++) {
for (int j = 1; j < n - 1; j++) {
if (grid[i][j] == 1 && !visited[i][j]) {
ans++;
}
}
}
return ans;
}
private void dfs(int i, int j, int[][] grid, boolean[][] visited) {
if (i < 0 || i > m - 1 || j < 0 || j > n - 1 || grid[i][j] == 0 || visited[i][j]) {
return;
}
visited[i][j] = true;
for (int k = 0; k < 4; k++) {
dfs(i + dx[k], j + dy[k], grid, visited);
}
}
}
总结
- 上述算法的时间复杂度是O(m * n), 空间复杂度是O(m * n)
- 坚持算法每日一题,加油!