输入: n = 3, m = 3, A = [[0,0],[0,1],[2,2],[2,1]]输出: [1,1,2,2]
解题思路:
用union find,每次操作都寻找周围4点,如果周围点是岛(坐标是1),就尝试联通。
注意:
1 Union 所有操作仅对父节点,并且只有父节点不一样时候才union。 P用index而非直接(x,y)
2 rank是树的高度, 为了优化空间和时间
3 此处count 从0开始 不是n
4 注意4个方向的遍历模板
```python
from typing import (
List,
)
from lintcode import (
Point,
)
"""
Definition for a point:
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
"""
class UnionFind:
def __init__(self, n):
self.father = [i for i in range(n)]
self.count = 0
self.rank = [1]*n
def find(self, p):
if self.father[p] != p:
self.father[p] = self.find(self.father[p])
return self.father[p]
def union(self, p, q):
fp = self.find(p)
fq = self.find(q)
if fp!= fq: #如果已经在同一岛, 不要count--
if self.rank[fp] > self.rank[fq]:
self.father[fq] = fp
elif self.rank[fq] > self.rank[fp]:
self.father[fp] = fq
else:
self.father[fp] = fq
self.rank[fq] += 1
self.count -= 1
def getCount(self):
return self.count
def addIsland(self):
self.count += 1
class Solution:
"""
@param n: An integer
@param m: An integer
@param operators: an array of point
@return: an integer array
"""
def num_islands2(self, n: int, m: int, operators: List[Point]) -> List[int]:
# write your code here
res = []
if not operators:
return res
uf = UnionFind(m*n)
grid = [[0]*m for _ in range(n)]
directions = [(1,0),(0,1),(-1,0),(0,-1)]
for p in operators:
x,y = p.x, p.y
if grid[x][y] == 1: #减枝 如果已经连过 无需再连
res.append(uf.getCount())
continue
index = x*m + y
uf.addIsland()
grid[x][y] = 1
for dx,dy in directions:
nx,ny = x+dx,y+dy
if 0 <= nx < n and 0 <= ny < m and grid[nx][ny] == 1:
uf.union(index, nx*m+ny)
res.append(uf.getCount())
return res
```