| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 数据结构学习笔记 2-3 并查集(Union-find)与 LeetCode真题(Java) -> 正文阅读 |
|
[数据结构与算法]数据结构学习笔记 2-3 并查集(Union-find)与 LeetCode真题(Java) |
2-3 并查集(Union-find)及经典问题并查集基础知识并查集是一个在学完树形结构之后,在树形结构基础之上的一个图论的数据结构。 并查集解决的问题:
一开始 0 ? 9 0-9 0?9 中每一个数字都是一个集合,首先我们把 4 4 4 和 3 3 3 之间画一条线,此时 4 4 4 和 3 3 3 就是一个集合,我们再把 3 3 3 和 8 8 8 连起来,原本只是一个 3 3 3 和 8 8 8 的集合,现在变成了 4 4 4 、 3 3 3、 8 8 8 的一个集合,所以得出连通性的问题是具有传递性的,比如 A A A 和 B B B 在一个集合, B B B 和 C C C 也在一个集合,那么 A A A 和 C C C 肯定也在一个集合。 那么我们怎么判断这些数是否在一个集合中呢?如下: Quick-Find算法
[ 4 ? 3 ] ? [ 3 ? 8 ] ? [ 6 ? 5 ] ? [ 9 ? 4 ] [4-3] \ [3-8]\ [6-5]\ [9-4] [4?3]?[3?8]?[6?5]?[9?4] 右面的
3
、
4
、
8
、
9
3、4、8、9
3、4、8、9 已经连通了,此时没有必要再连一次
[
8
?
9
]
[8-9]
[8?9] 了。 [ 2 ? 1 ] ? [ 5 ? 0 ] ? [ 7 ? 2 ] ? [ 6 ? 1 ] [2-1] \ [5-0]\ [7-2]\ [6-1] [2?1]?[5?0]?[7?2]?[6?1] 左面的
0
、
1
、
2
、
5
、
6
、
7
0、1、2、5、6、7
0、1、2、5、6、7 也已经连通了,
[
1
?
0
]
[1-0]
[1?0] 和
[
6
?
7
]
[6-7]
[6?7] 也没有必要再连一次了。 所有具有这样的连接关系,我们都可以把它类比成一棵树,像最后合并完成时,可以看做是这样的两棵树: 这两棵树放在一起,也可以叫做 “森林”,所以并查集也可以说是一种基于森林的算法。 代码实现染色
所以接下来我们要想办法优化合并操作。 Quick-Union算法
根节点的颜色是什么,我们整棵树的颜色就是什么,我们查询的时候只需要找到查询的节点所在的那棵树的根节点。 所以并查集本质是一个不记录子节点,只记录根节点的树。 假设一个子节点 8 8 8 的父节点是 3 3 3,我们可以创建一个 f a t h e r [ 8 ] = 3 father[8]=3 father[8]=3,这样就对我们之前的 c o l o r color color 数组做了一个优化,我们把单纯的染色关系变成了指向关系。 代码实现
虽然我们合并的操作优化为 O ( N ) → O ( T r e e ? H i g h t ) O(N)→O(Tree\ Hight) O(N)→O(Tree?Hight),但我们的查询操作由 O ( 1 ) → O ( T r e e ? H i g h t ) O(1)→O(Tree\ Hight) O(1)→O(Tree?Hight) 增加了,所以这个算法也是有问题的。 所以我们要在 Q u i c k ? U n i o n Quick-Union Quick?Union 基础上再做优化。 树越高,时间复杂度就越大,那么我们应该考虑,是按照 节点数量 还是 树的高度合并呢? 是树高深的树接到浅的上面 还是 节点多的树接在少的树上面?我们需要盖棺定论。 不难看出,一个树越高,它的平均查找次数也就越大,时间复杂度也就越大。 接下来我们对比一下两颗抽象的树: 此时我们发现,两棵树合并时,哪棵树的节点少,谁就做儿子。 所以我们可以加一个记录节点个数的数组。 Weighted Quick-Union算法
按秩合并 代码实现
F i n d Find Find 和 U n i o n Union Union 操作都优化为了 O ( l o g N ) O(logN) O(logN) 。 我们来进行最终优化——路径压缩。 Weighted Quick-Union With Path Compression算法
把我们整个链扁平化:
路径压缩 代码实现
F i n d Find Find 和 U n i o n Union Union 操作近似的都优化为了 O ( 1 ) O(1) O(1) 。 并查集总结在使用的时候尽量使用我们第四个最优化的算法,因为前三个都比较慢。
LeetCode真题经典面试题—并查集基础LeetCode547. 省份数量难度: 读完题发现,这道题描述的就是一个并查集的经典问题,题中的省份就是一个并查集的集合。 本题涉及到了图论的 在一个 n × n n×n n×n 的矩阵中, i s C o n n e c t e d [ i ] [ j ] = 1 isConnected[i][j] = 1 isConnected[i][j]=1 则代表第 i i i 个城市和第 j j j 个城市相连,分析第一个样例: 转换为邻接矩阵后发现 [ 1 , 2 ] [1, 2] [1,2] 和 [ 2 , 1 ] [2, 1] [2,1] 两个城市是连通的, 1 1 1 和 2 2 2 构成了 一个集合, 3 3 3 自己单独构成了一个集合, 所以返回 2 2 2 。 我们可以忽略对角线的 1 1 1,因为对角线代表的两个城市都只是自己。 LeetCode题解:代码实现 LeetCode200. 岛屿数量难度: 一个并查集的裸题,就是求在一个矩阵中,有几个 1 1 1 的集合。 具体细节实现看代码,有两个小trick: ① 二维数组中的查找优化:只需判断该点左和上方向的数。 ② 我们怎么合并上下左右为1的数字呢?利用二维数组的下标 给每一个数字一个编号。 LeetCode题解:代码实现 LeetCode990. 等式方程的可满足性难度: 这个题如果没学过并查集,想必很难做出来,但当你学过并查集之后,就很容易想到这就是一个维护集合的问题。 两个字母 a ? b a\ b a?b,中间的符号要么是 ! = != != 要么是 = = == ==; 如果是
=
=
==
== 就相当于是一次合并操作,我们就将
a
a
a 和
b
b
b 放入一个集合当中; LeetCode题解:代码实现 经典面试题—并查集进阶LeetCode684. 冗余连接难度: 一棵树 n n n 个节点, n ? 1 n-1 n?1 条边,题中的树: n n n 个节点, n n n 条边,所以多了这一条边,肯定会给这棵加一个环。 所以本题最终目的就是 就是在添加时判断是否已经连通过了。 LeetCode题解:代码实现 LeetCode1319. 连通网络的操作次数难度: c o n n e c t i o n s [ i ] = [ a , b ] connections[i] = [a,b] connections[i]=[a,b] 代表连接了 a a a 和 b b b,给了我们初始的连接方式,我们可以断开任意的线并连接到新的计算机中,求最小操作次数。 本质上还是求我们集合的数量。 3 3 3 个集合我们需要操作 2 2 2 次, 2 2 2 个集合我们需要操作 1 1 1 次,用并查集求解就简单了许多。 a n s = 集 合 数 量 ? 1 ans = 集合数量-1 ans=集合数量?1 LeetCode题解:代码实现 LeetCode128. 最长连续序列难度: 这道题用并查集来做的话,我们可以把连续的数字放到一个集合中,最后返回一个最大的集合。 我们怎么把连续的数放到一个集合呢? 示例1中,对于 2 2 2 这个数,它的相邻数字是 1 1 1 和 3 3 3,我们只需要把 1 1 1 和 3 3 3 的下标存入我们的集合即可,也就是 3 3 3 和 4 4 4,我们可以用哈希做映射。 对于封装的并查集类,我们需要加一个 c n t [ ] cnt[] cnt[] 来记录我们每个集合的大小。 LeetCode题解:代码实现 LeetCode947. 移除最多的同行或同列石头难度: 我们先把所有点都画出来,然后将所有同一行,同一列的点连起来,形成一个集合: 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。 所以我们可以将一个集合中 移动到只剩 1 1 1 个石子。 所以本题本质: LeetCode题解:代码实现 LeetCode1202. 交换字符串中的元素难度: 注意题中一句话:你可以 任意多次交换 在 只要把这句话理解了,那么你就会发现这道题可以用并查集求解。 示例1表述的并不是很清楚,我们看示例2: 这个 p a i r s pairs pairs 代表着 0 ? 1 ? 2 ? 3 0\ 1\ 2\ 3 0?1?2?3 都在一个集合中,所以 d c a b dcab dcab 可以进行任意次数的交换而达到字典序最小的 a b c d abcd abcd。 示例3: 这个 p a i r s pairs pairs 代表着 0 ? 1 ? 2 0\ 1\ 2 0?1?2 都在一个集合中,所以 c b a cba cba 可以进行任意次数的交换而达到字典序最小的 a b c abc abc。 所以上面的那句话的意思就是:我们可以 在一个集合中 任意交换集合中的元素 使得该集合的字典序最小。 我们可以对每个集合排序,那还有别的办法吗? 不难想到用堆来做,我们可以维护 n n n 个小顶堆,一个并查集的集合对应着一个堆,每次把堆顶元素 p o p ( ) pop() pop() 掉。 上篇文章讲了堆:数据结构学习笔记 2-2 堆(Heap)与优先队列与 LeetCode真题(Java) LeetCode题解:代码实现 经典面试题—附加选做题LeetCode765. 情侣牵手难度: N N N 对情侣一开始可能并没有坐到一起,我们要将其中的两个人交换,使得每对情侣坐到一起,求最少交换次数。 毕竟是一个 h a r d hard hard 题,我们找一下规律: 假如现在有 3 3 3 对情侣: ( 0 , 1 ) (0,1) (0,1) ( 2 , 3 ) (2,3) (2,3) ( 4 , 5 ) (4,5) (4,5) 那么在计算机中: 0 / 2 = 0 , 1 / 2 = 0 0/2=0,1/2=0 0/2=0,1/2=0 2 / 2 = 1 , 3 / 2 = 1 2/2=1,3/2=1 2/2=1,3/2=1 4 / 2 = 2 , 5 / 2 = 2 4/2=2,5/2=2 4/2=2,5/2=2 所以: N N N 对情侣我们就维护 N N N 个集合,这 3 3 3 对情侣的集合编号分别为 0 ? 1 ? 2 0\ 1\ 2 0?1?2。 如示例1所示: r o w = [ 0 , 2 , 1 , 3 ] row=[0,2,1,3] row=[0,2,1,3],他们两对情侣就属于下图左边的情况, 0 0 0 集合 和 1 1 1 集合有相交,所以此时只有 1 1 1 个集合,最少操次数就是 N ? 1 = 1 N-1=1 N?1=1。 如果 r o w = [ 0 , 1 , 2 , 3 ] row = [0, 1, 2, 3] row=[0,1,2,3],他们两对情侣就属于下图右边的情况, 0 0 0 集合 和 1 1 1 集合无相交,此时有 2 2 2 个集合,最少操次数就是 N ? 2 = 0 N-2=0 N?2=0,两对情侣本身就是挨在一起的,无需交换。 那么对于三对情侣: r o w = [ 0 , 2 , 1 , 4 , 5 , 3 ] row=[0, 2, 1, 4, 5, 3] row=[0,2,1,4,5,3],是否也成立呢? N ? 1 = 2 N - 1=2 N?1=2,最少交换次数的确是 2 2 2 次。 所以得出: 最 少 交 换 次 数 = 情 侣 对 数 ? 集 合 数 ? = > ? a n s = N ? c n t 最少交换次数=情侣对数-集合数\ =>\ ans = N - cnt 最少交换次数=情侣对数?集合数?=>?ans=N?cnt 找到了规律那么代码实现就很简单了。 LeetCode题解:代码实现 LeetCode685. 冗余连接 II难度: 在冗余连接Ⅰ中 是无向图,在冗余连接Ⅱ 中是有向图。 有向树:
我们可以用并查集来判断有向树是否有环,用一个 v i s [ ] vis[] vis[] 数组来记录每个节点的入度是多少。 所以我们的操作就是:删边建树 因为也有一条附加边,我们遍历每条边,判断删掉它之后 是否符合我们有向树的定义即可。 LeetCode题解:代码实现 总结
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 2:28:04- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |