并查集+省份数量

并查集数据结构

在这里插入图片描述
在这里插入图片描述

  1. 并查集是一种数据结构,并(Union)代表合并,查(Find)代表查找,集(Set)代表这是一个以字典为基础的数据结构,基本功能是合并集合中的元素,查找集合中的元素。
  2. 并查集的典型应用是有关连通分量的问题,并查集解决单个问题(添加,合并,查找)的时间复杂度都是O(1)。

数据结构

在并查集里面,每个节点会记录它的父节点

class UnionFind:
	def __init__(self):
		# 记录每个节点的父节点
		self.father = {}

如果节点互相连通(从一个节点可以达到另一个节点),那么他们的祖先是相同的。

初始化

当把一个新节点添加到并查集中,它的父节点应该为空。

    def add(self,x):
        """
        添加新节点
        """
        if x not in self.father:
            self.father[x] = None

在这里插入图片描述
在这里插入图片描述

合并两个节点

如果两个节点是连通的,那么就要把他们合并,也就是他们的祖先是相同的。

def merge(self, x, y):
	# 合并两个节点
	root_x, root_y = self.find(x), self.find(y)
	if root_x != root_y:
		self.father[root_x] = root_y

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

两个节点是否连通

判断两个节点是否处于同一个连通分量的时候,就要判断他们的祖先是否相同。

def is_connected(self,x,y):
	return self.find(x) == self.find(y)

查找祖先

如果节点的父节点不为空,那就不断迭代。

def find(self,x):
	# 查找根节点
	root = x
	while self.father[root] != None:
		root = self.father[root]
	return root

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class UnionFind:
    def __init__(self):
        self.father = {}
        # 额外记录集合的数量
        self.num_of_sets = 0
    
    def find(self,x):
        root = x
        
        while self.father[root] != None:
            root = self.father[root]
        
        while x != root:
            original_father = self.father[x]
            self.father[x] = root
            x = original_father
        
        return root
    
    def merge(self,x,y):
        root_x,root_y = self.find(x),self.find(y)
        
        if root_x != root_y:
            self.father[root_x] = root_y
            # 集合的数量-1
            self.num_of_sets -= 1
    
    def add(self,x):
        if x not in self.father:
            self.father[x] = None
            # 集合的数量+1
            self.num_of_sets += 1

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        uf = UnionFind()
        for i in range(len(M)):
            uf.add(i)
            for j in range(i):
                if M[i][j]:
                    uf.merge(i,j)
        
        return uf.num_of_sets

数组存储

class UnionFind:
    """并查集"""
    def __init__(self, n):
        self.parent = [i for i in range(n)]
        # 初始连通分量数为 n 个
        self.count = n
    
    def find(self, x):
        if x != self.parent[x]:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, u, v):
        u_root = self.find(u)
        v_root = self.find(v)
        # 合并,连通分量数减少
        if u_root != v_root:
            self.parent[u_root] = v_root
            self.count -= 1


class Solution:
    def findCircleNum(self, isConnected: List[List[int]]) -> int:

        n = len(isConnected)
        uf = UnionFind(n)
        for i in range(n):
            for j in range(i, n):
                if isConnected[i][j] == 1:
                    uf.union(i, j)
        return uf.count

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值