A 2d grid map of
m
rows and n
columns is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each addLand operation. 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:
Given
Initially, the 2d grid
m = 3, n = 3
, positions = [[0,0], [0,1], [1,2], [2,1]]
.Initially, the 2d grid
grid
is filled with water. (Assume 0 represents water and 1 represents land).0 0 0 0 0 0 0 0 0
Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.
1 0 0 0 0 0 Number of islands = 1 0 0 0
Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.
1 1 0 0 0 0 Number of islands = 1 0 0 0
Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.
1 1 0 0 0 1 Number of islands = 2 0 0 0
Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.
1 1 0 0 0 1 Number of islands = 3 0 1 0
We return the result as an array:
[1, 1, 2, 3]
Challenge:
Can you do it in time complexity O(k log mn), where k is the length of the
positions
?Solution:
The idea is to use Union-Find to connect all possible components.
For a given coordinate, we check if it can connect to its left, right, up, or down.
If its neighbor is an island, we union and update the number of components.
The time complexity is O(mn) and the space complexity is O(mn);
Code:
public class Solution { public List<Integer> numIslands2(int m, int n, int[][] positions) { List<Integer> result = new ArrayList<>(); if (positions == null || positions.length == 0) { return result; } if (positions[0] == null || positions[0].length == 0) { return result; } int islands = 0; int[] root = new int[m * n]; Arrays.fill(root, -1); int[] k = {1, 0, -1, 0, 1}; for (int[] point : positions) { int pt = point[0] * n + point[1]; root[pt] = pt; islands++; for (int i = 0; i < 4; i++) { int x= point[0] + k[i]; int y = point[1] + k[i + 1]; int nei = x * n + y; if (x < 0 || x >= m || y < 0 || y >= n || root[nei] == -1) { continue; } if (find(root, nei) != find(root, pt)) { root[find(root, nei)] = find(root, pt); islands--; } } result.add(islands); } return result; } public int find(int[] root, int i) { while (i != root[i]) { root[i] = root[root[i]]; i = root[i]; } return i; } }