修改数组【并查集】

这篇具有很好参考价值的文章主要介绍了修改数组【并查集】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

并查集

并查集就是对集合的合并和查询操作的统称。他要求参与运算的两个集合是不相交的(不含有相同的元素)。针对这两个集合可以进行的操作:
1.合并:将两个集合合并成一个集合。
2.查询:查询给定的两个元素是不是在同一个集合中。

并查集的表示方法

每一个并查集都使用一个树来表示,数的根用来标识整个集合,也就是说:判断两个元素是不是在同一个集合,就是看它们是不是有相同的根。
修改数组【并查集】

3和5有相同的根,它们属于同一个集合;3和7的根不同,它们属于不同的集合。
1和7的的根就是它们本身,也就是说判断一个集合的根的方法:就是找到一个节点,它的根就是它自己,那这个节点就是集合的根。

题目

给定一个长度为 N 的数组 A=[A 1,A 2 ,⋅⋅⋅,A N],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A 2,A 3 ,⋅⋅⋅,A N 。当修改 A i 时,小明会检查 A i是否在 A 1 ∼ A i−1 中出现过。如果出现过,则小明会给 A i 加上 1 ;如果新的 A i仍在之前出现过,小明会持续给 A i 加 1 ,直 到 A i没有在 A 1 ∼ A i −1 中出现过。当 A N也经过上述修改之后,显然 A 数组中就没有重复的整数了。现在给定初始的 A 数组,请你计算出最终的 A 数组。

输入描述

修改数组【并查集】
修改数组【并查集】

输入示例

5
2 1 1 3 4

输出示例

2 1 3 4 5

解题思路

那这一题如何使用并查集呢?
我们要通过一定的手段让所有的根节点(假设为a)都不能在A 1 ∼ A i −1 中出现,如果根节点在A 1 ∼ A i −1 中出现了,就要更改集合的根节点a为a+1的根节点。
如何判断一个数在A 1 ∼ A i −1 是已经出现过了呢?如果它是一个集合的根节点,那么它就没有在A 1 ∼ A i −1 出现过。此时就可以将它输出。如果它不是一个集合的根节点,那么就将它所在的集合的根节点a输出,同时需要将a的根节点更改为a+1。
有如下的例子:
修改数组【并查集】
但是此时存在一个问题:根节点是8的那个树实在是太深了,这会严重拖慢访问的速度。此时就需要进行路径压缩,类似于这样:

修改数组【并查集】

压缩路径之后变成:
修改数组【并查集】

但是在压缩路径的同时也在消耗时间,为了能够最大程度的节约时间,最优的做法是一边找根节点一边进行路径压缩,具体代码是:

#一边找根节点一边进行路径压缩的代码
def findRootAndZip(x):
	# 找到x的根节点
	if(x != root[x]): # root用于存储根节点,root[x]代表x的根节点
		# 如果x的根节点和x不相同,(因为只有根节点才满足它的根节点就是它自己)
		root[x] = findFaAndZip(root[x])
	return root[x]

根据上面的分析可以写出完成代码:

N = int(input())
numList = list(map(int,input().split()))
root = [i for i in range(100005)] # 存储根节点,刚开始i的根节点就是它自己

def findRootAndZip(x):
    # 发现根节点并且进行路径压缩的函数
    if(x!=root[x]):# 如果x和root[x]不相同了,说明root存储的不在是根节点了,而是父结点
        # 如果x的根节点和x不相同,x的根节点就是x的父结点的根节点
        root[x] = findRootAndZip(root[x])
    return root[x]



for i in range(N):
    a = numList[i]
    # 直接把a的根节点打印输出
    rot = findRootAndZip(a)
    print(rot,end=' ')
    # 同时a的根节点rot变成rot+1
    root[rot] = root[rot]+1

参考连接

连接文章来源地址https://www.toymoban.com/news/detail-471484.html

到了这里,关于修改数组【并查集】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 12.25~12.27并查集(查找与合并),全排列,约瑟夫问题(队列,数组)upper/lower_bound,重构二叉树,最优矩阵,线段树(构建),淘汰赛(构建树,队列),医院问题(最短路,弗洛伊德

    题目背景 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。 题目描述 规定:�x 和 �y 是亲戚,�y 和 �z 是亲戚,那么 �x 和 �z 也是亲戚。如果 �x,�y 是亲戚,那么 �

    2024年01月23日
    浏览(37)
  • LeetCode-200. 岛屿数量【深度优先搜索 广度优先搜索 并查集 数组 矩阵】

    给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 示例 1: 输入:grid = [ [“1”,“1”,“1”,“

    2024年04月14日
    浏览(28)
  • 并查集(种类并查集,带权并查集)

    链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网   动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 有人用两种说法对这N个动物所

    2024年02月11日
    浏览(29)
  • 【蓝桥模板】——如何用7行代码,优雅地拿捏并查集?(并查集模板)

    全文目录🧭 👩‍👩‍👦并查集-亲戚问题 🚀传送锚点​  💡思路点拨 🍞代码详解   👶🏻并查集-蓝桥幼儿园 🚀传送锚点  💡思路点拨 🍞代码详解   🌼并查集-合根植物 🚀传送锚点  💡思路点拨 🍞代码详解    🏰并查集-城邦 🚀传送锚点​​​​​​​  💡思

    2023年04月09日
    浏览(24)
  • 【数据结构】并查集

    并查集是简单的数据结构,学会并查集,为图打好基础。 是树状的数据结构,用于处理相交集合的合并与查询 通常用森林表示,一片森林表示一个集合 并查集一般需要完成 查找元素属于哪个集合 查看两个元素是否属于同一个集合 将两个集合归并成一个集合 集合的个数 假

    2024年02月19日
    浏览(28)
  • 并查集:推导部分和

    推导部分和 问题描述 对于一个长度为 N N N 的整数数列 A 1 , A 2 , ⋯ A N A_{1}, A_{2}, cdots A_{N} A 1 ​ , A 2 ​ , ⋯ A N ​ , 小蓝想知道下标 l l l 到 r r r 的部 分和 ∑ i = l r = A l + A l + 1 + ⋯ + A r sum_{i=l}^{r}=A_{l}+A_{l+1}+cdots+A_{r} ∑ i = l r ​ = A l ​ + A l + 1 ​ + ⋯ + A r ​ 是多少? 然而

    2024年02月11日
    浏览(26)
  • 并查集の进阶用法

    我们在处理问题的时候,可能会遇到一些需要维护每个元素所在的集合的问题,而并查集却恰好完美解决了这个问题。 对于普通的并查集,他支持的操作比较少,只有合并和查询,合并是指把两个集合合并成一个,而查询是询问两个元素是否在同一集合内;对于这两种操作,

    2024年02月02日
    浏览(28)
  • 数据结构--并查集

    所有元素的全集s 将各个元素划分为若干个互不相交的子集 用一个数组S[ ]即可表示“集合”关系 集合的两个基本操作―— “并” color{red}“并” “ 并 ” 和 “查” color{red}“查” “ 查 ” Find -—“查”操作:确定一个指定元素所属集合 Union --“并”操作:将两个不想交的集

    2024年02月15日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包