飞地的数量
难度:
标签:
题目描述
给你一个大小为 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
代码结果
运行时间: 67 ms, 内存: 27.7 MB
/*
* Problem Statement: Find the number of land cells (1s) in the grid that cannot reach the boundary of the grid using Java Streams.
* Solution Approach:
* 1. Mark all land cells connected to the boundary as visited using DFS.
* 2. Use streams to count the number of unvisited land cells.
*/
import java.util.Arrays;
public class Solution {
public int numEnclaves(int[][] grid) {
int rows = grid.length;
int cols = grid[0].length;
// Mark boundary connected lands
for (int i = 0; i < rows; i++) {
if (grid[i][0] == 1) dfs(grid, i, 0);
if (grid[i][cols - 1] == 1) dfs(grid, i, cols - 1);
}
for (int j = 0; j < cols; j++) {
if (grid[0][j] == 1) dfs(grid, 0, j);
if (grid[rows - 1][j] == 1) dfs(grid, rows - 1, j);
}
// Count the number of enclosed lands using streams
return Arrays.stream(grid)
.flatMapToInt(Arrays::stream)
.sum();
}
private void dfs(int[][] grid, int i, int j) {
int rows = grid.length;
int cols = grid[0].length;
if (i < 0 || j < 0 || i >= rows || j >= cols || grid[i][j] == 0) return;
grid[i][j] = 0; // Mark as visited
dfs(grid, i + 1, j);
dfs(grid, i - 1, j);
dfs(grid, i, j + 1);
dfs(grid, i, j - 1);
}
}
解释
方法:
此题目的核心思路是利用深度优先搜索(DFS)从矩阵的边缘开始搜索所有与边缘相连的陆地单元格,并将其标记为海洋(即将1变为0)。这样,矩阵中剩余的1即为被完全包围的陆地,无法通过移动到达边界。具体步骤包括:1. 从矩阵的四个边缘开始,对于每个边缘上的陆地单元格,执行DFS并标记所有可达的陆地单元格。2. 对整个矩阵进行遍历,统计未被标记(即未被转换为0的单元格)的陆地单元格数量,这些即为无法到达边界的陆地单元格。
时间复杂度:
O(m * n)
空间复杂度:
O(m * n)
代码细节讲解
🦆
在算法中,为什么首先从边缘的陆地单元格开始DFS,而不是从任意位置开始?
▷🦆
在DFS过程中,如何确保不会对同一个单元格进行重复的访问和处理?
▷🦆
DFS递归调用时,如果遇到矩阵的边界外或者海洋单元格,这种情况是如何处理的?
▷🦆
算法完成后,为什么可以直接统计二维数组中1的数量来得出结果?这里是否考虑了所有边界条件?
▷