diff --git a/leetcodes/305-number-of-islands-ii/305.cpp b/leetcodes/305-number-of-islands-ii/305.cpp new file mode 100644 index 0000000..1acbff2 --- /dev/null +++ b/leetcodes/305-number-of-islands-ii/305.cpp @@ -0,0 +1,75 @@ +class UnionFind { + public: + vector id; + + UnionFind(int n) : id(n, -1), rank(n) {} + + void unionByRank(int u, int v) { + const int i = find(u); + const int j = find(v); + if (i == j) + return; + if (rank[i] < rank[j]) { + id[i] = j; + } else if (rank[i] > rank[j]) { + id[j] = i; + } else { + id[i] = j; + ++rank[j]; + } + } + + int find(int u) { + return id[u] == u ? u : id[u] = find(id[u]); + } + + private: + vector rank; +}; + +class Solution { + public: + vector numIslands2(int m, int n, vector>& positions) { + constexpr int dirs[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + vector ans; + vector> seen(m, vector(n)); + UnionFind uf(m * n); + int count = 0; + + for (const vector& p : positions) { + const int i = p[0]; + const int j = p[1]; + if (seen[i][j]) { + ans.push_back(count); + continue; + } + seen[i][j] = true; + const int id = getId(i, j, n); + uf.id[id] = id; + ++count; + for (const auto& [dx, dy] : dirs) { + const int x = i + dx; + const int y = j + dy; + if (x < 0 || x == m || y < 0 || y == n) + continue; + const int neighborId = getId(x, y, n); + if (uf.id[neighborId] == -1) // water + continue; + const int currentRoot = uf.find(id); + const int neighborRoot = uf.find(neighborId); + if (currentRoot != neighborRoot) { + uf.unionByRank(currentRoot, neighborRoot); + --count; + } + } + ans.push_back(count); + } + + return ans; + } + + private: + int getId(int i, int j, int n) { + return i * n + j; + } +}; diff --git a/leetcodes/305-number-of-islands-ii/305.java b/leetcodes/305-number-of-islands-ii/305.java new file mode 100644 index 0000000..1760770 --- /dev/null +++ b/leetcodes/305-number-of-islands-ii/305.java @@ -0,0 +1,75 @@ +class UnionFind { + public int[] id; + + public UnionFind(int n) { + id = new int[n]; + rank = new int[n]; + Arrays.fill(id, -1); // water + } + + public void unionByRank(int u, int v) { + final int i = find(u); + final int j = find(v); + if (i == j) + return; + if (rank[i] < rank[j]) { + id[i] = j; + } else if (rank[i] > rank[j]) { + id[j] = i; + } else { + id[i] = j; + ++rank[j]; + } + } + + public int find(int u) { + return id[u] == u ? u : (id[u] = find(id[u])); + } + + private int[] rank; +} + +class Solution { + public List numIslands2(int m, int n, int[][] positions) { + final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + List ans = new ArrayList<>(); + boolean[][] seen = new boolean[m][n]; + UnionFind uf = new UnionFind(m * n); + int count = 0; + + for (int[] p : positions) { + final int i = p[0]; + final int j = p[1]; + if (seen[i][j]) { + ans.add(count); + continue; + } + seen[i][j] = true; + final int id = getId(i, j, n); + uf.id[id] = id; + ++count; + for (int[] dir : dirs) { + final int x = i + dir[0]; + final int y = j + dir[1]; + if (x < 0 || x == m || y < 0 || y == n) + continue; + final int neighborId = getId(x, y, n); + if (uf.id[neighborId] == -1) // Water + continue; + final int currentParent = uf.find(id); + final int neighborParent = uf.find(neighborId); + if (currentParent != neighborParent) { + uf.unionByRank(currentParent, neighborParent); + --count; + } + } + ans.add(count); + } + + return ans; + } + + private int getId(int i, int j, int n) { + return i * n + j; + } +} diff --git a/leetcodes/305-number-of-islands-ii/305.py b/leetcodes/305-number-of-islands-ii/305.py new file mode 100644 index 0000000..f321d02 --- /dev/null +++ b/leetcodes/305-number-of-islands-ii/305.py @@ -0,0 +1,64 @@ +class UnionFind: + def __init__(self, n: int): + self.id = [-1] * n + self.rank = [0] * n + + def unionByRank(self, u: int, v: int) -> None: + i = self.find(u) + j = self.find(v) + if i == j: + return + if self.rank[i] < self.rank[j]: + self.id[i] = j + elif self.rank[i] > self.rank[j]: + self.id[j] = i + else: + self.id[i] = j + self.rank[j] += 1 + + def find(self, u: int) -> int: + if self.id[u] != u: + self.id[u] = self.find(self.id[u]) + return self.id[u] + + +class Solution: + def numIslands2( + self, + m: int, + n: int, + positions: list[list[int]], + ) -> list[int]: + dirs = ((0, 1), (1, 0), (0, -1), (-1, 0)) + ans = [] + seen = [[False] * n for _ in range(m)] + uf = UnionFind(m * n) + count = 0 + + def getId(i: int, j: int, n: int) -> int: + return i * n + j + + for i, j in positions: + if seen[i][j]: + ans.append(count) + continue + seen[i][j] = True + id = getId(i, j, n) + uf.id[id] = id + count += 1 + for dx, dy in dirs: + x = i + dx + y = j + dy + if x < 0 or x == m or y < 0 or y == n: + continue + neighborId = getId(x, y, n) + if uf.id[neighborId] == -1: # water + continue + currentParent = uf.find(id) + neighborParent = uf.find(neighborId) + if currentParent != neighborParent: + uf.unionByRank(currentParent, neighborParent) + count -= 1 + ans.append(count) + + return ans