zoukankan      html  css  js  c++  java
  • 并查集

    1 并查集实际上可以看做是一个有向图的树,除了根节点指向自己,其它的节点都是向上指,指向其父节点,

    class UnionFindSets:
        def __init__(self, M):
            self.tree_num = len(M)
            # 初始化树的节点数
            self.tree_node_num = [1] * self.tree_num
            # 索引是节点,数组中的值是其父节点
            self.parent = [i for i in range(self.tree_num)]
        def union(self, node_i, node_j):
            root_i = self.find(node_i)
            root_j = self.find(node_j)
            # 如果是同一个根节点,则返回,无需合并,否则合并
            if root_i == root_j:
                return
            # 合并的时候小树往大树上合并,这样更加均衡,因为大树一般较高,往小树合并的话高度又会加一,导致越合越高,
            # 并且计算树的节点个数,方便合并时比较树的大小,
            if self.tree_node_num[root_i] > self.tree_node_num[root_j]:
                self.parent[root_j] = root_i
                self.tree_node_num[root_i] += self.tree_node_num[root_j]
            else:
                self.parent[root_i] = root_j
                self.tree_node_num[root_j] += self.tree_node_num[root_i]
            # 每合并一次减少一个树,树的数量减一
            self.tree_num -= 1
        # 查找节点所在树的根
        def find(self, node):
            # 如果还没有到根节点,就继续往上找
            while node != self.parent[node]:
                # 为了压缩树的高度,将当前节点连到其爷爷节点上,这样树的高度不超过3
                self.parent[node] = self.parent[self.parent[node]]
                # 更新当前节点,即向上走一个到其父节点
                node = self.parent[node]
            # 返回树的根节点
            return node
    from typing import List
    class Solution:
        def findCircleNum(self, M: List[List[int]]) -> int:
            uf = UnionFindSets(M)
            l = len(M)
            for row in range(l):
                for col in range(row):
                    # 如果为1,说明是朋友,进行连接
                    if M[row][col]:
                        uf.union(row, col)
            return uf.tree_num
    View Code

    2 并查集的优化有两种策略:

    (1)路径压缩;

    有“隔代压缩”与“完全压缩”。

           “隔代压缩”性能比较高,虽然压缩不完全,不过多次执行“隔代压缩”也能达到“完全压缩”的效果,我本人比较偏向使用“隔代压缩”的写法。
           “完全压缩”需要借助系统栈,使用递归的写法。或者先找到当前结点的根结点,然后把沿途上所有的结点都指向根结点,得遍历两次。

    (2)按秩合并。

           秩也有两种含义:① 秩表示以当前结点为根结点的子树结点总数,即这里的“秩”表示 size 含义;② 秩表示以当前结点为根结点的子树的高度,即这里的“秩”表示 rank 含义

  • 相关阅读:
    《C++ Primer》读书笔记—第十章 泛型算法
    悬浮在activity上的activity对话框
    android 双向滑动 稍加改进,可做成QQHD效果
    android String.format
    使用ttf字体
    UI界面设计准则
    scrollview gn gridview混合使用问题
    android Activity 之间传递复杂对象
    android程序获取手机imei方法
    android 自定义对话框
  • 原文地址:https://www.cnblogs.com/xxswkl/p/12795912.html
Copyright © 2011-2022 走看看