求连通块个数 - BFS、DFS、并查集实现
本文基于leetcode的200.岛屿数量(题目👇)为基础进行说明
DFS实现
class Solution:
def numIslands(self, grid) -> int:
vis = set()
directx = [-1, 1, 0, 0]
directy = [0, 0, -1, 1]
def DFS(x, y):
if (x, y) in vis:
return
vis.add((x, y))
for i in range(4):
newx = x + directx[i]
newy = y + directy[i]
if -1 < newx < len(grid) and -1 < newy < len(grid[0]):
if (newx, newy) not in vis and grid[newx][newy] == '1':
DFS(newx, newy)
s = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1' and (i, j) not in vis:
DFS(i, j)
# 进行了几次DFS就有多少块连通块
s += 1
return s
BFS实现
DFS和BFS两种实现方法类似,都是执行了几次操作,连通块就有几个。
class Solution:
def numIslands(self, grid) -> int:
if not grid:
return 0
row = len(grid)
col = len(grid[0])
vis = set()
directx = [-1, 1, 0, 0]
directy = [0, 0, -1, 1]
ans = 0
for i in range(row):
for j in range(col):
if grid[i][j] == '1' and (i, j) not in vis:
vis.add((i, j))
stack = [(i, j)]
ans += 1
while len(stack) != 0:
x, y = stack.pop(0)
for t in range(4):
newx, newy = x + directx[t], y + directy[t]
if -1 < newx < row and -1 < newy < col and (newx, newy) not in vis and grid[newx][newy] == '1':
vis.add((newx, newy))
stack.append((newx, newy))
return ans
并查集实现
class Solution:
def numIslands(self, grid) -> int:
directx = [-1, 1, 0, 0]
directy = [0, 0, -1, 1]
pre = {}
if not grid:
return 0
row = len(grid)
col = len(grid[0])
# 找首领
def find(node):
# 初始时,每个人都是自己的首领
pre.setdefault(node, node)
while node != pre[node]:
node = pre[node]
return node
# 将两个集合合并
def union(x, y):
pre[find(y)] = find(x)
for i in range(row):
for j in range(col):
if grid[i][j] == "1":
for t in range(4):
newx, newy = i + directx[t], j + directy[t]
if -1 < newx < row and -1 < newy < col and grid[newx][newy] == '1':
# 这里的i * col + j是为了将二维转换为一维,其中col的位置也可以替换成其他值,只要不影响到其他值即可
union(i * col + j, newx * col + newy)
res = set()
for i in range(row):
for j in range(col):
# 判断一共有几个大首领就知道有几个连通块了。
if grid[i][j] == "1":
res.add(find(i*col+j))
return len(res)