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 ...
随机推荐
- shell的if else 以及大于,小于等逻辑表达式
if ....; then .... elif ....; then .... else .... fi 大多数情况下,可以使用测试命令来对条件进行测试.比如可以比较字符串.判断文件是否存在及是否可读 ...
- w_all_checked - js -checkbox 多选、全选、submit、request
<!doctype html> <html> <head> <meta charset="UTF-8"> </head> ...
- Delphi 200X、XE中如何用并行实现循环的计算
interface uses Classes, SysUtils; type TParallelProc = reference to procedure(i: Integer; ThreadID: ...
- iframe框架里镶嵌页面;<marquee>:滚动效果;<mark>做标记;内联、内嵌、外联;选择器
标签:①②③④⑤⑥⑦★ 框架: 一.frameset:(框架集) 1.如果使用框架集,当前页面不能有body 2.cols="300,*":左右拆分,左边宽300,右边宽剩余 3. ...
- mysql storage enginees
这段时间在看<High Performance MySQL>,看到存储引擎这个地方感到很多细节比较陌生,所以总结小记一些 为 了适应各种不同的运行环境,MYSQL提供了多种不同的存储引擎( ...
- java多线程编程(一基础概念)
1.进程和线程 进程,是一个正在运行的程序实体,windows下常见的就是xxx.exe,在任务管理器中可以看见很多个进程.它是线程的容器. 线程,是进程中的一个执行流.在单线程编程中,我 ...
- Python 与 meta programming
meta programming: 编写能改变语言语法特性或者运行时特性的程序 Meta- 这个前缀在希腊语中的本意是「在…后,越过…的」,类似于拉丁语的 post-,比如 metaphysics 就 ...
- Linux学习之CentOS(十)--虚拟机下的CentOS如何上网
原地址:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/05/3001148.html 这篇随笔应该说跟CentOS的学习关系不是很大, ...
- POI简易帮助文档系列--给Excel设置样式
正如Html需要CSS一样,我们的POI生成的Excel同样需要样式才能更完美的表现我们的数据.下面还是从简单的例子出发,学习和了解POI的样式设计. 一.我的位置. package com.myja ...
- python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...