The basic idea is the Union-Find approach. We assign a root number for each island, and use an array to record this number. For each input, we check its four neighbor cells. If the neighbor cell is an island, then we retrieve the root number of this island. If two neighbor cells belong to two different islands, then we union them and therefore the total number of islands will become one less.

```
public List<Integer> numIslands2(int m, int n, int[][] positions) {
//use an array to hold root number of each island
int[] roots = new int[m*n];
//initialize the array with -1, so we know non negative number is a root number
Arrays.fill(roots, -1);
int[] xOffset ={0, 0, 1, -1};
int[] yOffset = {1, -1, 0, 0};
List<Integer> result = new ArrayList<Integer>();
for(int[] position : positions){
//for each input cell, its initial root number is itself
roots[position[0]*n + position[1]] = position[0]*n + position[1];
//count variable is used to count the island in current matrix.
//firstly, we assume current input is an isolated island
int count = result.isEmpty()? 1 : result.get(result.size()-1) + 1;
//check neighbor cells
for(int i = 0; i < 4; i++){
int newX = xOffset[i] + position[0];
int newY = yOffset[i] + position[1];
//if we found one neighbor is a part of island
if(newX >= 0 && newX < m && newY >= 0 && newY < n && roots[newX * n + newY] != -1){
//get the root number of this island
int root1 = find(newX * n + newY, roots);
//get the root number of input island
int root2 = roots[position[0]*n + position[1]];
//if root1 and root2 are different, then we can connect two isolated island together,
// so the num of island - 1
if(root1 != root2) count--;
//update root number accordingly
roots[root1] = root2;
}
}
result.add(count);
}
return result;
}
public int find(int target, int[] roots){
//found root
if(roots[target] == target) return target;
//searching for root and update the cell accordingly
roots[target] = find(roots[target], roots);
//return root number
return roots[target];
}
```