并查集与岛屿问题(leet200)

并查集解决岛屿问题,是一个经典的算法应用。本篇文章旨在帮助大家理解并查集算法,并实现在岛屿问题上的应用。

  • 并查集算法介绍

并查集是一种用于解决动态连通性问题的高效数据结构,为便于解释我们以岛屿问题为例,说明并查集的工作原理。

  • 岛屿问题

给定一个m*n的二位数组,其中1代表陆地,0代表海洋,如果一个陆地块的上下左右邻接着另一个陆地块,则称它们为一个岛屿。提问在给定二维数组中有几个岛屿?(输入输出样例如下)

要解决这个问题很简单,我们只需要把每一块陆地计算出它所属的岛屿标号(分组),然后统计所有标号的数目就是岛屿的数目。在最开始的时候我们认为每一个陆地块都是一个岛屿,之后我们通过“并”和“查”两个操作去不断地合并陆地块,并解决问题。

1.“查”算法

def find(x):
    if parent[x]!= x:
       return find(parent[x])
    return parent[x]

但是这样做有一个问题,随着不同子集不断地合并,查询的复杂度会脱离O1级别,最坏情况下达到链表ON级别。这种情况可以使用“路径压缩”进行优化,就是把查找过程的所有路径上的点的parent,改成它们共同的祖先。

def find(x):
    if parent[x]!=x: parent[x]=find[parent[x]]   #递归写法,最终会吧所有点连在根节点上
                                                 #构造一棵扁平的树
    return parent[x]

还有非递归写法,就是先用一个while循环找到祖先,再把路径上的点的parent都改成祖先。 

 

 

2."并"算法

def union(x,y):
    xroot, yroot = find(x),find(y)
    if xroot == yroot: return 
    parent[xroot] = yroot
    self.count -= 1

这里每执行一次并,岛屿数目减1。在实际中我们可以优化并算法,为每棵树维护一个深度,每次把深度小的树并到深度大的树上。 

for i in range(row):
    for j in range(col):
        if grid[i][j] == '0':
           continue
        index = i*col + j
        if j < col-1 and grid[i][j+1] == '1':
           union(index, index+1)
        if i < row-1 and grid[i+1][j] == '1':
           union(index, index+col)
return self.count

最后遍历整个二维数组中的陆地,看它右边和下边的点需不需要合并,最后返回岛屿数目。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章