Question 2 Number of Island II
Method 1: Brute Force(dfs)
for each position: add
Method 2
Why is a use case for Union Find?
动态图问题:每一次都加入一个新的点
Step 1: 思考时是不是Union Find的Use case: Yes
Step 1.5: Union Find开多长
长度m* n
即便是没有给Board也要自己记录Board为什么?
为了union的时候知道邻居是不是1
Step 2:思考要union什么
上下左右四个方向1
周围的1一定有老大(一定是一个联通分量了)
一个一个operation,一个个query,一个个position(防止重复,防止超界invalid)
detail
我们的result从何而来?result是每一次有多少个联通分量,一开始这个图里其实全是0(水),一开始的count= 0;
一般来说,union只能让count变得更少,在哪家这个count呢?每次来一个点,我们就直接默认他自己租整了一个单独的岛,如果他能union别人,union里会吧count减到正常值。
public List<Integer> numIsland2(int m, int n, int[][] positions) {
int[][] graph = new int[m][n];
List<Integer> result = new ArrayList<>();
UF uf = new UF(m * n);
for (int[] position : positions) {
int x = position[0];
int y = position[1];
if (graph[x][y] == 1) {
result.add(uf.count);
continue;
}
graph[x][y] = 1;
uf.count++;
for (int[] dir: dirs) {
int neiX = x + dir[0];
int neiY = y + dir[1];
if (isValid(graph, neiX, neiY) && graph[neiX][neiY] == 1) {
uf.union(x * n + y, neiX* n +neiY);
}
}
return result;
}
}
class UF{
int[] laoda;
int count;
public UF(int n) {
this.laoda = new int[n];
for (int i = 0; i < n; i++) {
laoda[i] = i;
}
this.count = 0; ///注意这个0
}
public void union(int a, int b) {
int alaoda = find(a);
int blaoda = find(b);
if (alaoda != blaoda) {
laoda[alaoda] = blaoda;
count--; //注意这里
}
}
public int find(int a) {
return laoda[a] = laoda[a] == a? a: find(laoda[a]);
}
}
这个方法快在哪?为什么动态图就这么快?
对于每一次的变化
dfs: 变了我重来一次,刚才算过我再算一次
uf:对于变化的部分union起来,以前算过的仍然存在
Last updated