Leetcode: Number of Islands II && Summary of Union Find
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 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?
Union Find
Princeton's lecture note on Union Find in Algorithms and Data Structures It is a well organized note with clear illustration describing from the naive QuickFind to the one with Weighting and Path compression. With Weighting and Path compression, The algorithm runs in
O((M+N) log* N) where M is the number of operations ( unite and find ), N is the number of objects, log* is iterated logarithm while the naive runs in O(MN).
方法一: Union Find based on Quick Find
我觉得:Union复杂度: O(M*N), where M is the number of calls of Union, and N is the size of id array, in our case N=m*n
Find复杂度: O(1)
实际运行时间199ms
public class Solution {
public List<Integer> numIslands2(int m, int n, int[][] positions) {
int[][] dirs = new int[][]{{-1,0},{1,0},{0,1},{0,-1}};
unionFind uf = new unionFind(m*n);
List<Integer> res = new ArrayList<Integer>();
for (int[] pos : positions) {
int cur = pos[0]*n + pos[1];
uf.ids[cur] = cur;
uf.count++;
for (int[] dir : dirs) {
int x = dir[0] + pos[0];
int y = dir[1] + pos[1];
int nb = x*n+y;
if (x<0 || x>=m || y<0 || y>=n || uf.ids[nb]==-1) continue;
if (uf.find(nb) != uf.find(cur)) {
uf.union(nb, cur);
}
}
res.add(uf.count);
}
return res;
}
public class unionFind {
int[] ids;
int count;
public unionFind(int num) {
this.ids = new int[num];
Arrays.fill(ids, -1);
this.count = 0;
}
public int find(int num) {
return ids[num];
}
public boolean union(int n1, int n2) {
int id1=ids[n1], id2=ids[n2];
if (id1 != id2) {
for (int i=0; i<ids.length; i++) {
if (ids[i] == id2) {
ids[i] = id1;
}
}
count--;
return true;
}
return false;
}
}
}
Faster Union Find方法2:Union Find Based on Quick Union 参考:https://leetcode.com/discuss/69572/easiest-java-solution-with-explanations
Quick Union is Faster than Quick Find
The idea is simple. To represent a list of islands, we use trees. i.e., a list of roots. This helps us find the identifier of an island faster. If roots[c] = p means the parent of node c is p, we can climb up the parent chain to find out the identifier of an island, i.e., which island this point belongs to:
Do root[root[roots[c]]]... until root[c] == c;
To transform the two dimension problem into the classic UF, perform a linear mapping:
int id = n * x + y;
Initially assume every cell are in non-island set {-1}. When point A is added, we create a new root, i.e., a new island. Then, check if any of its 4 neighbors belong to the same island. If not,union the neighbor by setting the root to be the same. Remember to skip non-island cells.
我觉得:Union复杂度: O(M*logN), where M is the number of calls of Union, and N is the size of id array, in our case N=m*n
Find复杂度: O(logN)
实际运行28ms
public class Solution {
public List<Integer> numIslands2(int m, int n, int[][] positions) {
int[][] dirs = new int[][]{{-1,0},{1,0},{0,1},{0,-1}};
unionFind uf = new unionFind(m*n);
List<Integer> res = new ArrayList<Integer>();
for (int[] pos : positions) {
int cur = pos[0]*n + pos[1];
uf.ids[cur] = cur;
uf.count++;
for (int[] dir : dirs) {
int x = dir[0] + pos[0];
int y = dir[1] + pos[1];
int nb = x*n+y;
if (x<0 || x>=m || y<0 || y>=n || uf.ids[nb]==-1) continue;
int rootNb = uf.root(nb);
int rootCur = uf.root(cur);
if (rootCur != rootNb) { //not connect
uf.union(rootCur, rootNb);
uf.count--;
}
}
res.add(uf.count);
}
return res;
}
public class unionFind { //ids[]记录上一跳pos,root记录最上面的pos,union(i, j)修改i的root的上一跳为j的root
int[] ids;
int count;
public unionFind(int num) {
this.ids = new int[num];
Arrays.fill(ids, -1);
this.count = 0;
}
public int root(int i) { //FIND operation is proportional to the depth of the tree.the average running time is O(logN)
while (ids[i] != i) i = ids[i];
return i;
}
public boolean isConnected(int i, int j) {
return root(i) == root(j);
}
public void union(int i, int j) {
int iRoot = root(i);
int jRoot = root(j);
ids[iRoot] = jRoot;
}
}
}
Summary of Union Find:
Princeton's lecture note on Union Find
Quick Find

Quick Union
Here is a very easy understanding video by Stanford(看3:00开始的例子,非常简单, 一看就懂)

Compare of Fast Find & Fast Union, though worst case time complexity is almost the same, fast union is faster than fast find

Leetcode: Number of Islands II && Summary of Union Find的更多相关文章
- [LeetCode] Number of Islands II 岛屿的数量之二
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
- LeetCode – Number of Islands II
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
- [LeetCode] Number of Islands II
Problem Description: A 2d grid map of m rows and n columns is initially filled with water. We may pe ...
- [LeetCode] Number of Islands 岛屿的数量
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...
- [LeetCode] 305. Number of Islands II 岛屿的数量之二
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
- LeetCode 305. Number of Islands II
原题链接在这里:https://leetcode.com/problems/number-of-islands-ii/ 题目: A 2d grid map of m rows and n column ...
- [LeetCode] 305. Number of Islands II 岛屿的数量 II
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
- 305. Number of Islands II
题目: A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand ...
- [Swift]LeetCode305. 岛屿的个数 II $ Number of Islands II
A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...
随机推荐
- hiho48 : 欧拉路·一
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最后的宝藏.现在他们控制的 ...
- 把Java程序打包成jar文件包并执行
1.首先要确认自己写的程序有没有报错. 2.第一次我写的是Web Project到现在,我一直没有执行成功,所以最好创建的是java Project 打包步骤: 1.在项目上,右键,选择Export. ...
- PHP 依赖注入 (转)
说这个话题之前先讲一个比较高端的思想--'依赖倒置原则' "依赖倒置是一种软件设计思想,在传统软件中,上层代码依赖于下层代码,当下层代码有所改动时,上层代码也要相应进行改动,因此维护成本较高 ...
- 【Java 基础篇】【第一课】HelloWorld
有点C++基础,现在需要快速的学会java,掌握java,所以就这样了,写点博客,以后看起来也好回顾. 1.第一步 javaSDK和Eclipse下载就不说了,搞定了这两样之后: 2.打开Eclips ...
- C++位操作符总结
#include <stdio.h> #include <memory.h> #include <malloc.h> #define MaxBinLength 16 ...
- pch找不到pod里头文件
1. 问题描述 将文件用pod管理起来后,pod install成功,而且这些文件也可以搜索得到,但是pch文件里import的头文件找不到,而这些头文件又确确实实在你的pod项目下. 2. 解决办法 ...
- [LeetCode] Maximal Rectangle(good)
Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and ...
- 转:ASP.NET MVC利用TryUpdateModel来做资料更新 (二)
前言 第一篇說明了 TryUpdateModel 的簡單的應用,除了可指定更新的欄位之外也可排除更新特定的欄位,而因為可搭配 Metadata 做欄位驗證為資料又做了一層把關,但在 ASP.NET M ...
- 【转】Android绘制View的过程研究——计算View的大小
Android绘制View的过程研究——计算View的大小 转自:http://liujianqiao398.blog.163.com/blog/static/18182725720121023218 ...
- 破解Mysql数据库密码
破解Mysql数据库密码 点我,点我,破解mysql数据库密码: