原题
给定 n,m,分别代表一个2D矩阵的行数和列数,同时,给定一个大小为 k 的二元数组A。起初,2D矩阵的行数和列数均为 0,即该矩阵中只有海洋。二元数组有 k 个运算符,每个运算符有 2 个整数 A[i].x, A[i].y,你可通过改变矩阵网格中的A[i].x],[A[i].y] 来将其由海洋改为岛屿。请在每次运算后,返回矩阵中岛屿的数量。
样例
给定 n = 3, m = 3, 二元数组 A =[(0,0),(0,1),(2,2),(2,1)].
返回 [1,1,2,2].
解题思路
- 作为Number of Islands的follow up,可以同样使用DFS或者BFS,每次加入新的点就再全部遍历一次二维数组 - 每次遍历O(mn),如果一共k次操作,总的时间复杂度为O(km*n)
- 由于每次操作只是把一块海洋变成陆地,它影响的点只可能是上下左右四个位置,如果是1,将它们合并。
- 集合合并 - 使用并查集,换句话说只有可能改变四个点的father
- 初始化时,每个点的father是自己的ID = x*列数 + y
- 全局变量 count = 0, 每次增加一个点 count += 1
- 考虑上下左右四个位置是否能够合并,每次合并 count -= 1
- 最终时间复杂度降为O(k*4) ~ O(k)
完整代码
# Definition for a point.
# class Point:
# def __init__(self, a=0, b=0):
# self.x = a
# self.y = b
class UnionFind:
def __init__(self, m, n):
self.father = {}
for i in range(n):
for j in range(m):
id = self.converttoId(i,j,m);
self.father[id] = id
def converttoId(self, x, y, m):
return x*m + y
def find(self, x):
parent = self.father[x]
while parent != self.father[parent]:
parent = self.father[parent]
return parent
def compressed_find(self, x):
parent = self.father[x]
while parent != self.father[parent]:
parent = self.father[parent]
temp = -1;
fa = self.father[x]
while fa != self.father[fa]:
temp = self.father[fa]
self.father[fa] = parent
fa = temp
return parent
def union(self, x, y):
fa_x = self.find(x)
fa_y = self.find(y)
if fa_x != fa_y:
self.father[fa_x] = fa_y
class Solution:
# @param {int} n an integer
# @param {int} m an integer
# @param {Pint[]} operators an array of point
# @return {int[]} an integer array
def numIslands2(self, n, m, operators):
dx = [0,-1, 0, 1]
dy = [1, 0, -1, 0]
island = [[0 for i in range(m)] for j in range(n)]
ans = []
uf = UnionFind(n, m)
count = 0
if operators != None:
for i in range(len(operators)):
count += 1
x = operators[i].x
y = operators[i].y
if island[x][y] != 1:
island[x][y] = 1
id = uf.converttoId(x, y, m)
# 计算上下左右四个点的位置
for j in range(4):
nx = x + dx[j]
ny = y + dy[j]
if 0 <= nx and nx < n and 0 <= ny and ny < m and island[nx][ny] == 1:
nid = uf.converttoId(nx, ny, m)
fa = uf.find(id)
nfa = uf.find(nid)
if fa != nfa:
count -= 1
uf.union(id, nid)
ans.append(count)
return ans
网友评论