并查集

今天接了字节数据开发实习的一面,面试官问了我一个类似于计算无向图的连通分量数量的代码题,面试官引导我往图方面想,当时没撕出来,还是对图算法不熟悉!

想的是通过DFS遍历,需要遍历几次DFS能够遍历所有的节点,那么就有几个连通分量。

后面在网上又搜集到了一种新的解题思路,所以在这里记录学习一下。

题目:

一下2维列表中[0, 1]表示 0关注1 ,【3, 2】表示3关注2,【3, 4】表示3关注4,那么【3,2,4】应该属于一个社交圈,现有以下2维列表,求出共有多少个社交圈(连通图)

[[0, 1],

[3,2],

[2,3],

[4, 5],

[3, 4],

[3,5]]

算法思想:

class UnionFindSet(object):
    def __init__(self, m):
 
        # m, n = len(grid), len(grid[0])
        self.roots = [i for i in range(m)]
        # rank用来干啥?? 一种用于并查集的秩优化 的数据结构 初始化成0
        self.rank = [0 for i in range(m)] 
        self.count = m  #初始化成m个连通分量
        
 
    def find(self, member): 
        # 找到父节点
        # 父节点定义:该集团的头头
        
        tmp = []# 存储member向父节点追溯的链式关系节点
        while member != self.roots[member]: #通过遍历链式关系 找到父节点 并且用tmp列表存起来链式关系的节点  直到 member节点为最终的父节点为止
            # 添加到tmp中
            tmp.append(member)
            member = self.roots[member] # 继续寻找链式关系 直到 member节点为最终的父节点为止
        for root in tmp:# 更新链式关系中的每个节点为最后的父节点
            self.roots[root] = member
        return member # 返回最后的父节点
        
    def union(self, p, q): # 合并两个集团
        parentP = self.find(p) # 找到p的父节点
        parentQ = self.find(q) # 找到Q的父节点
        if parentP != parentQ: # 如果父节点不同  那就合并两个集合
            if self.rank[parentP] > self.rank[parentQ]:  # p父节点 0 q父节点  -1  
                self.roots[parentQ] = parentP # 把q的父节点设成p
            elif self.rank[parentP] < self.rank[parentQ]:  # p父节点-1 q父节点 0
                self.roots[parentP] = parentQ # 把p的父节点设成q
            else:  # p父节点 0 q父节点 0 或者 p父节点 -1 q父节点 -1
                self.roots[parentQ] = parentP  # 默认q的父节点设成p的父节点
                self.rank[parentP] -= 1 #  p的父节点的rank设为-1
            self.count -= 1 # 最终的连通分量-1
 
class Solution(object):
    def countComponents(self, n, edges):
        """
        :type n: int
        :type edges: List[List[int]]
        :rtype: int
        """
        # 定义好需要用的数据结构
        # 初始化成n个连通分量 通过添加边 合并连通分量集合 更新连通分量的父节点
        ufs = UnionFindSet(n)
        
        for edge in edges:
            # 遍历边 不断的合并
            start, end = edge[0], edge[1]
            
            ufs.union(start, end)
            
        return ufs.count # 返回最终的连通分量数
    
n = 6
edges = [[0, 1],[3,2],[2,3],[4, 5],[3, 4],[3,5]]
so = Solution()
num = so.countComponents(n, edges)
print(num)             
            

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值