Time: 20190903
Type: Medium
给定编号从 0 到 n-1 的 n 个节点和一个无向边列表(每条边都是一对节点),请编写一个函数来计算无向图中连通分量的数目。
示例 1:
输入: n = 5 和 edges = [[0, 1], [1, 2], [3, 4]]
0 3
| |
1 --- 2 4
输出: 2
示例 2:
输入: n = 5 和 edges = [[0, 1], [1, 2], [2, 3], [3, 4]]
0 4
| |
1 --- 2 --- 3
输出: 1
注意:
你可以假设在 edges 中不会出现重复的边。而且由于所以的边都是无向边,[0, 1] 与 [1, 0] 相同,所以它们不会同时在 edges 中出现。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-connected-components-in-an-undirected-graph
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
还是先用最简单的并查集的写法来找到小团伙的个数。因为不是检测环,所以没有必要在Union函数中判断两个点的父亲是不是相同,来决定有没有环。
只需要在连通完毕后,遍历各个节点的大哥是谁,用集合过滤一下,统计一下个数即可。
class UnionFind:
def __init__(self):
# 这样初始化是和题意相符的
self.par = list(range(5001))
def find(self, x):
if x != self.par[x]:
self.par[x] = self.find(self.par[x])
return self.par[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
self.par[py] = px
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
uf = UnionFind()
# 先联合
for e in edges:
uf.union(e[0], e[1])
# 此时开始判断有多少个子集,用集合过滤
cnt = 0
seen = set()
for i in range(0, n):
this_par = uf.find(i)
if this_par not in seen:
seen.add(this_par)
cnt += 1
return cnt
并查集用的是一维数组来表示各个节点的爸爸,初始化时自身是爸爸,上面自己定义了5001个元素,好像和要解的题没有关系,其实是假定题目中的n个结点不超过5001,可以按照真实的结点数传入:
class UnionFind:
def __init__(self, nums):
# 这样初始化是和题意相符的
self.par = list(range(nums))
def find(self, x):
if x != self.par[x]:
self.par[x] = self.find(self.par[x])
return self.par[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
self.par[py] = px
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
uf = UnionFind(n)
# 先联合
for e in edges:
uf.union(e[0], e[1])
# 此时开始判断有多少个子集
cnt = 0
seen = set()
for i in range(0, n):
this_par = uf.find(i)
if this_par not in seen:
seen.add(this_par)
cnt += 1
print(seen)
return cnt
再写一遍非递归版本的find:
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
class UnionFind:
def __init__(self, nums):
self.par = list(range(nums))
def find(self, x):
r = x
while r != self.par[r]:
r = self.par[r]
# 路径压缩
i = x
while i != r:
tmp = self.par[i]
self.par[i] = r
i = tmp
return r
def union(self, x, y):
xr = self.find(x)
yr = self.find(y)
self.par[yr] = xr
uf = UnionFind(n)
for edge in edges:
uf.union(edge[0], edge[1])
# 开始统计小团伙的数量
count = 0
seen = set()
for i in range(n):
p = uf.find(i)
if p not in seen:
count += 1
seen.add(p)
return count
END.