Question
You are given an empty 2D binary grid grid
of size m x n
. The grid represents a map where 0
's represent water and 1
's represent land. Initially, all the cells of grid
are water cells (i.e., all the cells are 0
's).
We may perform an add land operation which turns the water at position into a land. You are given an array positions
where positions[i] = [ri, ci]
is the position (ri, ci)
at which we should operate the ith
operation.
Return an array of integers answer
where answer[i]
is the number of islands after turning the cell (ri, ci)
into a land.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
Algorithm
Find the final components count in a forrest.
The point for this question is how you construct the graph(the connection of nodes).
Code
Standard answer
class UnionFind { int[] parent; int[] rank; int count; public UnionFind(int size) { parent = new int[size]; rank = new int[size]; for (int i = 0; i < size; i++) parent[i] = -1; count = 0; } public void addLand(int x) { if (parent[x] >= 0) return; parent[x] = x; count++; } public boolean isLand(int x) { if (parent[x] >= 0) { return true; } else { return false; } } int numberOfIslands() { return count; } public int find(int x) { if (parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } public void union(int x, int y) { int xset = find(x), yset = find(y); if (xset == yset) { return; } else if (rank[xset] < rank[yset]) { parent[xset] = yset; } else if (rank[xset] > rank[yset]) { parent[yset] = xset; } else { parent[yset] = xset; rank[xset]++; } count--; } } class Solution { public List<Integer> numIslands2(int m, int n, int[][] positions) { int x[] = { -1, 1, 0, 0 }; int y[] = { 0, 0, -1, 1 }; UnionFind dsu = new UnionFind(m * n); List<Integer> answer = new ArrayList<>(); for (int[] position : positions) { int landPosition = position[0] * n + position[1]; dsu.addLand(landPosition); for (int i = 0; i < 4; i++) { int neighborX = position[0] + x[i]; int neighborY = position[1] + y[i]; int neighborPosition = neighborX * n + neighborY; // If neighborX and neighborY correspond to a point in the grid and there is a // land at that point, then merge it with the current land. if (neighborX >= 0 && neighborX < m && neighborY >= 0 && neighborY < n && dsu.isLand(neighborPosition)) { dsu.union(landPosition, neighborPosition); } } answer.add(dsu.numberOfIslands()); } return answer; } }
This code is my initial code and cannot pass the test case:
3
3
[[0,1],[1,2],[2,1],[1,0],[0,2],[0,0],[1,1]]
I tried use the sum and product of the position[i][j]
as the index in union find. But forget the simplest one, i*n+j
flatten the matrix. I believe if I make things easier like this, I could have come up with the final answer.
class Solution { int[][][] parents; int count; int[][] grid; public List<Integer> numIslands2(int m, int n, int[][] positions) { count = 0; List<Integer> res = new ArrayList<>(); if (positions == null || positions.length == 0 || positions[0] == null || positions[0].length == 0) { return res; } parents = new int[m][n][2]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { parents[i][j] = new int[]{i, j}; } } grid = new int[m][n]; for (int[] position : positions) { int x = position[0]; int y = position[1]; grid[x][y] = 1; count++; union(position, m, n); res.add(count); } return res; } private int[] find(int[] position) { int x = position[0]; int y = position[1]; if (x != parents[x][y][0] && y != parents[x][y][1]) { parents[x][y] = find(parents[x][y]); } return parents[x][y]; } private void union(int[] position, int m, int n) { int x = position[0]; int y = position[1]; int[] xRoot = find(parents[x][y]); if (x-1 >= 0 && grid[x-1][y] == 1) { int[] leftRoot = find(parents[x-1][y]); if (xRoot[0] != leftRoot[0] || xRoot[1] != leftRoot[1]) { parents[xRoot[0]][xRoot[1]] = leftRoot; count--; } } if (x+1 < m && grid[x+1][y] == 1) { int[] rightRoot = find(parents[x+1][y]); if (xRoot[0] != rightRoot[0] || xRoot[1] != rightRoot[1]) { parents[xRoot[0]][xRoot[1]] = rightRoot; count--; } } if (y-1 >= 0 && grid[x][y-1] == 1) { int[] upperRoot = find(parents[x][y-1]); if (xRoot[0] != upperRoot[0] || xRoot[1] != upperRoot[1]) { parents[xRoot[0]][xRoot[1]] = upperRoot; count--; } } if (y + 1 < n && grid[x][y+1] == 1) { int[] lowerRoot = find(parents[x][y+1]); if (xRoot[0] != lowerRoot[0] || xRoot[1] != lowerRoot[1]) { parents[xRoot[0]][xRoot[1]] = lowerRoot; count--; } } } }