Union Find算法基础

Union Find算法用于处理集合的合并和查询问题,其定义了两个用于并查集的操作:

  • Find: 确定元素属于哪一个子集,或判断两个元素是否属于同一子集
  • Union: 将两个子集合并为一个子集

并查集是一种树形的数据结构,其可用数组或unordered_map表示:

Find操作即查找元素的root,当两元素root相同时判定他们属于同一个子集;Union操作即通过修改元素的root(或修改parent)合并子集,下面两个图展示了id[6]由6修改为9的变化:

  

图片来源 这里

Union Find算法应用

Union Find可用于解决集合相关问题,如判断某元素是否属于集合、两个元素是否属同一集合、求解集合个数等,算法框架如下:

    //261. Graph Valid Tree
    bool validTree(int n, vector<pair<int, int>>& edges) {
        vector<);
        for(auto edge:edges){
            //find查看两点是否已在同一集合
            int x=find(num,edge.first);
            int y=find(num,edge.second);
            if(x==y) return false;  //两点已在同一集合情况下则出现环
            //union让两点加入同一集合
            num[x]=y;
        }
        ==edges.size();
    }
    int find(vector<int>&num,int i){
        ) return i;
        return find(num,num[i]);  //id[id[...id[i]...]]
    }

一些情况下为清晰和解偶会将Uinon Find实现为一个类,独立出明显的Union和Find两个操作。

相关LeetCode题:

261. Graph Valid Tree  题解

547. Friend Circles  题解

947. Most Stones Removed with Same Row or Column  题解

200. Number of Islands  题解

 

算法优化

有两种常用的方法用来降低并查集树形结构的高度、以减少Uinon Find算法的时间复杂度,这两种方法是:

Weighting(或称作Ranking): 使用多一个数组记录每个集合的size,Uinon时将size小的集合挂到size大的集合下,例如:

对3、5 Uinon,因3所在集合元素size 4大于5所在集合元素size 2,将6挂到9下而不是将9挂到6下。

Path compression: 对一个集合下的元素直接挂到root之下,而不是挂到其parent,path compression实现很简单只需在Find中加一行代码:

    string find(unordered_map<string,string>& root,string s){
        if(root[s]!=s)
            root[s]=find(root,root[s]);
        return root[s];
    }

加入path compression也能实现减少并查集树高度的效果,图示如下:

Weighting和Path compression两种方法可以同时使用,这样使得对N个元素进行M次Union Find操作的时间复杂度可以减少到 (M+N)lgN。因lgN随N的增长变化很小,所以整体算法时间复杂度接近于线性的时间复杂度。

相关LeetCode题:

924. Minimize Malware Spread  题解

算法与数据结构基础 - 合并查找(Union Find)的更多相关文章

  1. 算法与数据结构基础 - 折半查找(Binary Search)

    Binary Search基础 应用于已排序的数据查找其中特定值,是折半查找最常的应用场景.相比线性查找(Linear Search),其时间复杂度减少到O(lgn).算法基本框架如下: //704. ...

  2. 算法与数据结构基础 - 图(Graph)

    图基础 图(Graph)应用广泛,程序中可用邻接表和邻接矩阵表示图.依据不同维度,图可以分为有向图/无向图.有权图/无权图.连通图/非连通图.循环图/非循环图,有向图中的顶点具有入度/出度的概念. 面 ...

  3. 算法与数据结构基础 - 分治法(Divide and Conquer)

    分治法基础 分治法(Divide and Conquer)顾名思义,思想核心是将问题拆分为子问题,对子问题求解.最终合并结果,分治法用伪代码表示如下: function f(input x size ...

  4. 算法与数据结构基础 - 数组(Array)

    数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...

  5. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  6. 算法与数据结构基础 - 广度优先搜索(BFS)

    BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...

  7. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

  8. 算法与数据结构基础 - 二叉树(Binary Tree)

    二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...

  9. 算法与数据结构基础 - 双指针(Two Pointers)

    双指针基础 双指针(Two Pointers)是面对数组.链表结构的一种处理技巧.这里“指针”是泛指,不但包括通常意义上的指针,还包括索引.迭代器等可用于遍历的游标. 同方向指针 设定两个指针.从头往 ...

随机推荐

  1. C# 使用表达式树获取特性的值

    一.定义特性 /// <summary> /// 定义特性 /// </summary> [AttributeUsage(AttributeTargets.Field | At ...

  2. .Net Core Api 授权认证

    一.所使用到的NuGet: 1. System.IdentityModel.Tokens.Jwt 2. Microsoft.AspNetCore.Authentication.JwtBearer 二. ...

  3. Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析

    缘由 数据存储在MYSQ库中,数据基本维持不变,但数据量又较大(几千万)放在MYSQL中查询效率上较慢,寻求一种简单有效的方式提高查询效率,MYSQL并不擅长大规模数据量下的数据查询. 技术方案 考虑 ...

  4. 对象属性 Object.getOwnPropertyNames() Object.keys for...in

    1.Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组. Object.getOwn ...

  5. 关于ftp响应码的分析【转载】

    转载地址: http://www.jb51.net/article/26649.htm 1开头-成功 2开头-成功 3开头-权限问题 4开头-文件问题 5开头-服务器问题 150 FILE: %s 1 ...

  6. VUE动态(自动)Loading【绑定到URL】,同页面多个Loading互不冲突

    需求来源:当使用React时,使用 umi loading 很方便,页面对http请求发生改变时,也会自动改变loading的相关状态(true/false) 对VUE插件进行找寻,发现没找到合适内容 ...

  7. win10 安装mysql(图文详情)避免卡在最后一步

    win10 安装mysql 本人安装mysql一般都是在镜像文件夹中下载(http://mirrors.sohu.com/),最近系统重做了之后安装mysql5.5.msi,可以安装成功.但是在最后的 ...

  8. Catalan公式

    f(n)=f(1)*f(n-1)+f(2)*f(n-2)+f(3)*f(n-3)+......+f(n-1)*f(1) 例用:一个长度为n的无重复序列入栈的所有出栈方式

  9. 使用canvas来完成线性渐变和径向渐变的功能

    fillStyle的第二种使用情况就是渐变色的填充.渐变色就分为线性渐变色和径向渐变色.   线性渐变:大致分为两步 这里又会使用到canvas的两个新的函数.   第一步 : 使用一个新的函数cre ...

  10. tar 命令详解(持续更新)

    可以用man tar查看tar命令使用的权威解释 Main operation mode: -c: 建立压缩档案 -r:向压缩归档文件末尾追加文件 -t:查看内容 -u:更新原压缩包中的文件 -x:解 ...