publicintClosedIsland(int[][] grid) { int m = grid.Length; int n = grid[0].Length; int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { Queue<Tuple<int, int>> qu = new Queue<Tuple<int, int>>(); grid[i][j] = 1; bool closed = true;
qu.Enqueue(new Tuple<int, int>(i, j)); while (qu.Count > 0) { Tuple<int, int> tuple = qu.Dequeue(); int cx = tuple.Item1, cy = tuple.Item2; if (cx == 0 || cy == 0 || cx == m - 1 || cy == n - 1) { closed = false; } for (int d = 0; d < 4; d++) { int nx = cx + dir[d][0]; int ny = cy + dir[d][1]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 0) { grid[nx][ny] = 1; qu.Enqueue(new Tuple<int, int>(nx, ny)); } } } if (closed) { ans++; } } } } return ans; } }
const dir = [[-1, 0], [1, 0], [0, -1], [0, 1]]; var closedIsland = function(grid) { const m = grid.length; const n = grid[0].length; let ans = 0; for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (grid[i][j] === 0) { const qu = []; grid[i][j] = 1; let closed = true;
qu.push([i, j]); while (qu.length) { const arr = qu.shift(); let cx = arr[0], cy = arr[1]; if (cx === 0 || cy === 0 || cx === m - 1 || cy === n - 1) { closed = false; } for (let d = 0; d < 4; d++) { let nx = cx + dir[d][0]; let ny = cy + dir[d][1]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] === 0) { grid[nx][ny] = 1; qu.push([nx, ny]); } } } if (closed) { ans++; } } } } return ans; };
for (inti=0; i < m; i++) { for (intj=0; j < n; j++) { if (grid[i][j] == 0 && dfs(i, j, grid, m, n)) { ans++; } } } return ans; }
publicbooleandfs(int x, int y, int[][] grid, int m, int n) { if (x < 0 || y < 0 || x >= m || y >= n) { returnfalse; } if (grid[x][y] != 0) { returntrue; } grid[x][y] = -1; booleanret1= dfs(x - 1, y, grid, m, n); booleanret2= dfs(x + 1, y, grid, m, n); booleanret3= dfs(x, y - 1, grid, m, n); booleanret4= dfs(x, y + 1, grid, m, n); return ret1 && ret2 && ret3 && ret4; } }
publicclassSolution { publicintClosedIsland(int[][] grid) { int ans = 0; int m = grid.Length; int n = grid[0].Length;
for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0 && DFS(i, j, grid, m, n)) { ans++; } } } return ans; }
publicboolDFS(int x, int y, int[][] grid, int m, int n) { if (x < 0 || y < 0 || x >= m || y >= n) { returnfalse; } if (grid[x][y] != 0) { returntrue; } grid[x][y] = -1; bool ret1 = DFS(x - 1, y, grid, m, n); bool ret2 = DFS(x + 1, y, grid, m, n); bool ret3 = DFS(x, y - 1, grid, m, n); bool ret4 = DFS(x, y + 1, grid, m, n); return ret1 && ret2 && ret3 && ret4; } }
booldfs(int x, int y, int** grid, int m, int n) { if (x < 0 || y < 0 || x >= m || y >= n) { returnfalse; } if (grid[x][y] != 0) { returntrue; } grid[x][y] = -1; bool ret1 = dfs(x - 1, y, grid, m, n); bool ret2 = dfs(x + 1, y, grid, m, n); bool ret3 = dfs(x, y - 1, grid, m, n); bool ret4 = dfs(x, y + 1, grid, m, n); return ret1 && ret2 && ret3 && ret4; };
intclosedIsland(int** grid, int gridSize, int* gridColSize) { int ans = 0; int m = gridSize; int n = gridColSize[0];
for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0 && dfs(i, j, grid, m, n)) { ans++; } } } return ans; }
classSolution: defclosedIsland(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) ans = 0
defdfs(x: int, y: int) -> bool: if x < 0or y < 0or x >= m or y >= n: returnFalse if grid[x][y] != 0: returnTrue grid[x][y] = -1 ret1, ret2, ret3, ret4 = dfs(x - 1, y), dfs(x + 1, y), dfs(x, y - 1), dfs(x, y + 1) return ret1 and ret2 and ret3 and ret4 for i inrange(m): for j inrange(n): if grid[i][j] == 0and dfs(i, j): ans += 1 return ans
classSolution { public: intclosedIsland(vector<vector<int>>& grid){ int m = grid.size(), n = grid[0].size(); UnionFind uf(m * n);
for (int i = 0; i < m; i++) { if (grid[i][0] == 0) { uf.uni(i * n, 0); } if (grid[i][n - 1] == 0) { uf.uni(i * n + n - 1, 0); } } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 0) { uf.uni(j, 0); } if (grid[m - 1][j] == 0) { uf.uni((m - 1) * n + j, 0); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { if (i > 0 && grid[i - 1][j] == 0) { uf.uni(i * n + j, (i - 1) * n + j); } if (j > 0 && grid[i][j - 1] == 0) { uf.uni(i * n + j, i * n + j - 1); } } } }
unordered_set<int> cnt; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { cnt.emplace(uf.find(i * n + j)); } } } int total = cnt.size(); if (cnt.count(uf.find(0))) { total--; } return total; } };
publicclassSolution { publicintClosedIsland(int[][] grid) { int m = grid.Length, n = grid[0].Length; UnionFind uf = new UnionFind(m * n);
for (int i = 0; i < m; i++) { if (grid[i][0] == 0) { uf.Uni(i * n, 0); } if (grid[i][n - 1] == 0) { uf.Uni(i * n + n - 1, 0); } } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 0) { uf.Uni(j, 0); } if (grid[m - 1][j] == 0) { uf.Uni((m - 1) * n + j, 0); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { if (i > 0 && grid[i - 1][j] == 0) { uf.Uni(i * n + j, (i - 1) * n + j); } if (j > 0 && grid[i][j - 1] == 0) { uf.Uni(i * n + j, i * n + j - 1); } } } }
ISet<int> cnt = new HashSet<int>(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { cnt.Add(uf.Find(i * n + j)); } } } int total = cnt.Count; if (cnt.Contains(uf.Find(0))) { total--; } return total; } }
voiduni(UnionFind* obj, int x, int y) { int rootx = find(obj, x); int rooty = find(obj, y); if (rootx != rooty) { if (obj->rank[rootx] > obj->rank[rooty]) { obj->parent[rooty] = rootx; } elseif (obj->rank[rootx] < obj->rank[rooty]) { obj->parent[rootx] = rooty; } else { obj->parent[rooty] = rootx; obj->rank[rootx]++; } } }
intclosedIsland(int** grid, int gridSize, int* gridColSize) { int m = gridSize, n = gridColSize[0]; UnionFind *uf = creatUnionFind(m * n); for (int i = 0; i < m; i++) { if (grid[i][0] == 0) { uni(uf, i * n, 0); } if (grid[i][n - 1] == 0) { uni(uf, i * n + n - 1, 0); } } for (int j = 1; j < n - 1; j++) { if (grid[0][j] == 0) { uni(uf, j, 0); } if (grid[m - 1][j] == 0) { uni(uf, (m - 1) * n + j, 0); } } for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { if (i > 0 && grid[i - 1][j] == 0) { uni(uf, i * n + j, (i - 1) * n + j); } if (j > 0 && grid[i][j - 1] == 0) { uni(uf, i * n + j, i * n + j - 1); } } } }
HashItem *cnt = NULL; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 0) { hashAddItem(&cnt, find(uf, i * n + j)); } } } int total = HASH_COUNT(cnt); if (hashFindItem(&cnt, find(uf, 0))) { total--; } freeUnionFind(uf); hashFree(&cnt); return total; }
var closedIsland = function(grid) { const m = grid.length; const n = grid[0].length; const uf = newUnionFind(m * n);
for (let i = 0; i < m; i++) { if (grid[i][0] === 0) { uf.uni(i * n, 0); } if (grid[i][n - 1] === 0) { uf.uni(i * n + n - 1, 0); } } for (let j = 1; j < n - 1; j++) { if (grid[0][j] === 0) { uf.uni(j, 0); } if (grid[m - 1][j] === 0) { uf.uni((m - 1) * n + j, 0); } } for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (grid[i][j] === 0) { if (i > 0 && grid[i - 1][j] === 0) { uf.uni(i * n + j, (i - 1) * n + j); } if (j > 0 && grid[i][j - 1] === 0) { uf.uni(i * n + j, i * n + j - 1); } } } }
const cnt = newSet(); for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (grid[i][j] === 0) { cnt.add(uf.find(i * n + j)); } } } let total = cnt.size; if (cnt.has(uf.find(0))) { total--; } return total; };
classUnionFind { constructor(n) { this.parent = newArray(n); for (let i = 0; i < n; i++) { this.parent[i] = i; } this.rank = newArray(n).fill(0); }
if parent_[x] != x: parent_[x] = self.find(parent_[x]) return parent_[x]
classSolution: defclosedIsland(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) uf = UnionFind(m * n)
for i inrange(m): if grid[i][0] == 0: uf.uni(i * n, 0) if grid[i][n - 1] == 0: uf.uni(i * n + n - 1, 0) for j inrange(1, n - 1): if grid[0][j] == 0: uf.uni(j, 0) if grid[m - 1][j] == 0: uf.uni((m - 1) * n + j, 0) for i inrange(m): for j inrange(n): if grid[i][j] == 0: if i > 0and grid[i - 1][j] == 0: uf.uni(i * n + j, (i - 1) * n + j) if j > 0and grid[i][j - 1] == 0: uf.uni(i * n + j, i * n + j - 1)
cnt = set() for i inrange(m): for j inrange(n): if grid[i][j] == 0: cnt.add(uf.find(i * n + j)) total = len(cnt) if uf.find(0) in cnt: total -= 1 return total
复杂度分析
时间复杂度:时间复杂度:O(mn \times \alpha(mn)),其中 m 和 n 分别是矩阵的行数和列数,\alpha 是反阿克曼函数。并查集的初始化需要 O(m \times n) 的时间,然后遍历 m \times n 个元素,最多执行 m \times n 次合并操作,这里的并查集使用了路径压缩和按秩合并,单次操作的时间复杂度是 O(\alpha(m \times n)),因此并查集合并的操作的时间复杂度是 O(mn \times \alpha(mn)),总时间复杂度是 O(mn + mn \times \alpha(mn)) = O(mn \times \alpha(mn))。