LeetCode编程训练 - 合并查找(Union Find)
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<int> num(n,-);
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;
}
return n-==edges.size();
}
int find(vector<int>&num,int i){
if(num[i]==-) return i;
return find(num,num[i]); //id[id[...id[i]...]]
}
一些情况下为清晰和解偶会将Uinon Find实现为一个类,独立出明显的Union和Find两个操作。
相关LeetCode题:
947. Most Stones Removed with Same Row or Column 题解
算法优化
有两种常用的方法用来降低并查集树形结构的高度、以减少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 题解
LeetCode编程训练 - 合并查找(Union Find)的更多相关文章
- LeetCode编程训练 - 折半查找(Binary Search)
Binary Search基础 应用于已排序的数据查找其中特定值,是折半查找最常的应用场景.相比线性查找(Linear Search),其时间复杂度减少到O(lgn).算法基本框架如下: //704. ...
- Leetcode 编程训练
Leetcode这个网站上的题都是一些经典的公司用来面试应聘者的面试题,很多人通过刷这些题来应聘一些喜欢面试算法的公司,比如:Google.微软.Facebook.Amazon之类的这些公司,基本上是 ...
- Leetcode 编程训练(转载)
Leetcode这个网站上的题都是一些经典的公司用来面试应聘者的面试题,很多人通过刷这些题来应聘一些喜欢面试算法的公司,比如:Google.微软.Facebook.Amazon之类的这些公司,基本上是 ...
- 算法与数据结构基础 - 合并查找(Union Find)
Union Find算法基础 Union Find算法用于处理集合的合并和查询问题,其定义了两个用于并查集的操作: Find: 确定元素属于哪一个子集,或判断两个元素是否属于同一子集 Union: 将 ...
- LeetCode编程训练 - 滑动窗口(Sliding Window)
滑动窗口基础 滑动窗口常用来解决求字符串子串问题,借助map和计数器,其能在O(n)时间复杂度求子串问题.滑动窗口和双指针(Two pointers)有些类似,可以理解为往同一个方向走的双指针.常用滑 ...
- LeetCode编程训练 - 拓扑排序(Topological Sort)
拓扑排序基础 拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序 ...
- LeetCode编程训练 - 位运算(Bit Manipulation)
位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...
- LeetCode编程训练 - 回溯(Backtracking)
回溯基础 先看一个使用回溯方法求集合子集的例子(78. Subsets),以下代码基本说明了回溯使用的基本框架: //78. Subsets class Solution { private: voi ...
- 每日一道 LeetCode (19):合并两个有序数组
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
随机推荐
- STM32 USB 鼠标+键盘 串口控制
*MOS0101000000# 鼠标左键按下 *MOS0102000000# 鼠标右键按下 *MOS0103000000# 鼠标中键按下 *MOS0100000000# 鼠标抬起 *MOS01000a ...
- gradle 编译kafka源码慢
我前提已经在环境变量中将GRADLE_HOME设置到了gradle的目录(在E盘),并且在环境变量里设置了本地仓库GRADLE_USER_HOME. 编译kafka源码时候,很慢很慢.百度了一下,有说 ...
- js获取当前时间并实时刷新
效果如图: 代码如下: <html> <head> <title>js获取当前时间并实时刷新</title> <script> //页面加载 ...
- MiniGUI 如何显示繁体字
有两种编码格式都可以显示繁体字,一种是GBK,一种是BIG5: 由于MiniGUI官方提供的字库的字体大小太小,所以只得自己去做字库,我用一个字库生成软件,分别做了一个GBK编码的字库和一个BIG5编 ...
- 认识uWSGI、uwsgi、wsgi
WSGI协议 首先弄清下面几个概念: WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web ...
- 关于vue的computed、filters、watch
filters 这个属性大家可能用的不是很多 因为一般的数组过滤我们用 es6的filter就能完成了 我想到一个场景,网上买书促销 满100减50 满两百减100 <input type=&q ...
- EXTJS4.2 内存中操作表格数据时,删除表格数据,行号不连续解决
需要重新刷新下表格的view => grid.view.refresh();
- 如何从Eclipse导入github上的项目源码--转载
[转载出处声明:hil2000的专栏] 1.首先在github.com上申请一个账号,比如笔者的账号为puma0072.Eclipse需要安装egit插件,在Eclipse中选择help->Ma ...
- Eclipse 那些小技巧(值得收藏)
1.菜单命令系列 Edit→content Assist→add Alt+/ 代码关联 Windows→Next Editor→add Ctrl+Tab 切换窗口 Run→Debug Toggle L ...
- symfony小练习-表白墙
过上一个博客系统以及对官方示例程序的基本学习,目前对symfony的各个组件有了一定的学习,学校布置了一个表白墙任务,这里就这个任务的完成进行记录 ...........2019.3.20.22.31 ...