二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。
请返回 封闭岛屿 的数目。
示例 1:
输入:grid = [[1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0]]
输出:2
解释:
灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。答案
var closedIsland = function(grid) {
const n = grid.length, m = grid[0].length
let ans = 0
const dfs = (i, j) => {
if (i < 0 || i >= n || j < 0 || j >= m) return false
if (grid[i][j] === 1) return true
grid[i][j] = 1
const a = dfs(i + 1, j)
const b = dfs(i - 1, j)
const c = dfs(i, j + 1)
const d = dfs(i, j - 1)
return a && b && c && d
}
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (grid[i][j] === 0 && dfs(i, j) === true) ans++
}
}
return ans
};
function closedIsland(grid: number[][]): number {
const n = grid.length, m = grid[0].length
let ans = 0
const dfs = (i, j) => {
if (i < 0 || i >= n || j < 0 || j >= m) return false
if (grid[i][j] === 1) return true
grid[i][j] = 1
const a = dfs(i + 1, j)
const b = dfs(i - 1, j)
const c = dfs(i, j + 1)
const d = dfs(i, j - 1)
return a && b && c && d
}
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (grid[i][j] === 0 && dfs(i, j) === true) ans++
}
}
return ans
};
func closedIsland(grid [][]int) int {
n, m, ans := len(grid), len(grid[0]), 0
var dfs func(int, int) bool
dfs = func(i int, j int) bool {
if i < 0 || i >= n || j < 0 || j >= m {
return false
}
if grid[i][j] == 1 {
return true
}
grid[i][j] = 1
a, b, c, d := dfs(i + 1, j), dfs(i - 1, j), dfs(i, j + 1), dfs(i, j - 1)
return a && b && c && d
}
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if grid[i][j] == 0 && dfs(i, j) == true {
ans++
}
}
}
return ans
}
class Solution {
function closedIsland($grid) {
$n = count($grid);
$m = count($grid[0]);
$ans = 0;
for ($i = 0; $i < $n; $i++) {
for ($j = 0; $j < $m; $j++) {
if ($grid[$i][$j] === 0) {
$queue = [[$i, $j]];
$closed = true;
while (count($queue) > 0) {
list($x, $y) = array_shift($queue);
if ($x < 0 || $x >= $n || $y < 0 || $y >= $m) {
$closed = false;
continue;
}
if ($grid[$x][$y] === 1) continue;
$grid[$x][$y] = 1;
$queue []= array($x + 1, $y);
$queue []= array($x - 1, $y);
$queue []= array($x, $y + 1);
$queue []= array($x, $y - 1);
}
if ($closed === true) $ans++;
}
}
}
return $ans;
}
}
class Solution {
public int closedIsland(int[][] grid) {
int n = grid.length, m = grid[0].length, ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 0) {
Queue<int[]> q = new ArrayDeque<int[]>();
q.offer(new int[]{i, j});
boolean closed = true;
while (q.isEmpty() == false) {
int[] node = q.poll();
int x = node[0], y = node[1];
if (x < 0 || y < 0 || x >= n || y >= m) {
closed = false;
continue;
}
if (grid[x][y] == 1) continue;
grid[x][y] = 1;
q.offer(new int[]{x + 1, y});
q.offer(new int[]{x - 1, y});
q.offer(new int[]{x, y + 1});
q.offer(new int[]{x, y - 1});
}
if (closed == true) ans++;
}
}
}
return ans;
}
}
const int dr[4][2] = ;
int closedIsland(int** grid, int gridSize, int* gridColSize){
int ans = 0;
int q[gridSize * gridColSize[0] * 5][2];
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < *gridColSize; j++) {
if (grid[i][j] == 0) {
int head = 0, tail = 1;
q[head][0] = i;
q[head][1] = j;
bool closed = true;
while (head < tail) {
int* node = q[head++];
int x = node[0], y = node[1];
if (x < 0 || x >= gridSize || y < 0 || y >= *gridColSize) {
closed = false;
continue;
}
if (grid[x][y] == 1) continue;
grid[x][y] = 1;
for (int k = 0; k < 4; k++) {
q[tail][0] = x + dr[k][0];
q[tail][1] = y + dr[k][1];
tail++;
}
}
if (closed == true) ans++;
}
}
}
return ans;
}
class UnionFind {
private:
vector<int> parent;
vector<int> sizes;
int cnt;
public:
UnionFind(int n) {
cnt = n;
parent = vector<int>(n, 0);
sizes = vector<int>(n, 1);
while (n--) parent[n] = n;
}
int find(int x) {
while (x != parent[x]) x = parent[parent[x]];
return x;
}
void connect(int x, int y) {
int rootX = find(x), rootY = find(y);
if (rootX == rootY) return;
if (sizes[rootX] >= sizes[rootY]) {
parent[rootY] = rootX;
sizes[rootX]++;
} else {
parent[rootX] = rootY;
sizes[rootY]++;
}
cnt--;
}
int size() {
return cnt;
}
void minusCnt() {
cnt--;
}
};
class Solution {
public:
int closedIsland(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
UnionFind u(n * m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 0) {
if (i + 1 < n && grid[i + 1][j] == 0) u.connect(i * m + j, (i + 1) * m + j);
if (j + 1 < m && grid[i][j + 1] == 0) u.connect(i * m + j, i * m + j + 1);
} else {
u.minusCnt();
}
}
}
unordered_set<int> rootSet;
for (int i = 0; i < n; i++) {
if (grid[i][0] == 0) rootSet.emplace(u.find(i * m));
if (grid[i][m - 1] == 0) rootSet.emplace(u.find(i * m + m - 1));
}
for (int j = 0; j < m; j++) {
if (grid[0][j] == 0) rootSet.emplace(u.find(j));
if (grid[n - 1][j] == 0) rootSet.emplace(u.find((n - 1) * m + j));
}
return u.size() - rootSet.size();
}
};
class UnionFind:
def __init__(self, n: int):
self.cnt = n
self.parents = [0] * n
self.sizes = [1] * n
while n > 0:
self.parents[n - 1] = n - 1
n -= 1
def size(self) -> int:
return self.cnt
def find(self, x: int) -> int:
while x != self.parents[x]: x = self.parents[self.parents[x]]
return x
def union(self, x: int, y: int):
rootX, rootY = self.find(x), self.find(y)
if rootX == rootY: return
if self.sizes[rootX] >= self.sizes[rootY]:
self.parents[rootY] = rootX
self.sizes[rootX] += 1
else:
self.parents[rootX] = rootY
self.sizes[rootY] += 1
self.cnt -= 1
def minusCnt(self):
self.cnt -= 1
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
n, m = len(grid), len(grid[0])
u = UnionFind(n * m)
for i in range(0, n):
for j in range(0, m):
if grid[i][j] == 0:
if i + 1 < n and grid[i + 1][j] == 0: u.union(i * m + j, (i + 1) * m + j)
if j + 1 < m and grid[i][j + 1] == 0: u.union(i * m + j, i * m + j + 1)
else: u.minusCnt()
rootSet = set()
for i in range(0, n):
if grid[i][0] == 0: rootSet.add(u.find(i * m))
if grid[i][m - 1] == 0: rootSet.add(u.find(i * m + m - 1))
for j in range(0, m):
if grid[0][j] == 0: rootSet.add(u.find(j))
if grid[n - 1][j] == 0: rootSet.add(u.find((n - 1) * m + j))
return u.size() - len(rootSet)