Question:
Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator.
Given n
= 3
, m
= 3
, array of pair A = [(0,0),(0,1),(2,2),(2,1)]
.
return [1,1,2,2]
.
0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent.
原题链接:http://www.lintcode.com/en/problem/number-of-islands-ii/
这题可以用disjoint-set来实现。关于disjoint-set的基本概念,以下的这个视频讲解的十分清楚。视频链接:https://www.youtube.com/watch?v=ID00PMy0-vE
我们首先实现disjoint-set的数据结构。在disjoint-set中,每一个节点有3个属性,父亲节点、rank值(近似深度)和数据。定义Node如下:
class Node{ int rank; int data; Node parant; }
其次,disjoint-set有3个方法,makeSet(int data):创建一个单独的集合;findSet(int data):寻找该数据所在集合的代表节点(根节点);union(int data1, int data2):合并两个集合。另外,我们需要一个HashMap来储存数据和其对应节点的映射。
public class DisjointSet { private Map<Integer, Node> map = new HashMap<Integer, Node>(); public boolean makeSet(int data){ if(map.containsKey(data)) return false; else{ Node node = new Node(); node.rank = 0; node.data = data; node.parant = node; map.put(data, node); return true; } } public int findSet(int data){ if(!map.containsKey(data)) return -1; return findSet(map.get(data)).data; } public Node findSet(Node node){ Node parant = node.parant; if(parant == node) return node; node.parant = findSet(parant); return node.parant; } public void union(int data1, int data2){ Node parant1 = findSet(map.get(data1)); Node parant2 = findSet(map.get(data2)); if(parant1 == parant2) return; if(parant1.rank>=parant2.rank){ parant1.rank = parant1.rank==parant2.rank?parant1.rank+1:parant1.rank; parant2.parant = parant1; } else { parant1.parant = parant2; } } }
假设m次操作,n个元素,其时间复杂度为O(m α(n)),其中α(n)是一个增长极慢的函数,在实际应用中小于4,因此时间复杂度约为O(m)。 最后,我们的问题就变得十分简单。对于每一次将海变成岛屿的操作,相当于一次makeSet的操作,然后对其四周进行findSet操作,如果其值不为-1,那么进行union操作。因此,对于每一次makeSet操作,最多需要4次union操作,时间复杂度为O(1),对于k次操作,时间复杂度为O(k)。