题目信息
LeetoCode地址: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
题目理解
原题使用的是名称和账号的邮箱地址,好多字母,可能有些人会不太好理解。我换了一种场景:联想一下,诸如《魔兽世界》《地下城与勇士》这样的网络游戏,每个玩家都可以创建多个游戏角色,每个游戏角色的ID都是服务器唯一的。注意,玩家的姓名在现实生活中是完全可以重复的。
在下图上半部分里,有一些玩家: 两位周小董, 两位张小涵,他们都拥有一些游戏角色。
按照题目的意思,因为两个周小董都拥有角色《战斗至死》,所以这两个周小董其实同一个人,他们的游戏角色是可以直接合并,属于同一个人的。
相反的,因为两位张小涵的游戏角色都不重复,所以这是两位重名的玩家,他们的游戏角色是不应该合并的。
综上,如下图下半部分所示,最终周小董合并之后有三个游戏角色,而两位张小涵的游戏角色保持不变。

由于玩家合并之后,一定没有两位玩家拥有相同的角色,所以可以得出结论,所有的角色ID都是独一无二的,而不像合并前有重复。
解题思路
数组并查集+哈希表
我们已经知道最终合并之后是不存在重复的角色ID的,找到它们并确定哪个游戏角色属于哪个玩家是很简单的,使用HashMap就可以做到。问题的关键在于如何找到相同玩家的不同角色ID,并将他们合并。
首先,我们先给所有第一次出现角色ID按照从0开始递增的方式编号. 可以看到,我们总共有0到5也就是6个不重复的角色ID.

要合并它们,我们可以换个思考方式。那就是除了利用玩家名字之外,还有没有别的办法表示一批角色ID是属于同一个人的?实际是有的!我们可以使用每个玩家的第一个角色作为这一批角色的父亲,或者叫做根。如果用图表示,就类似下面这样:

现在,让我们聚焦到根是《0.一往无前》和《3.逍遥自在》的这两个树状结构。

显而易见的,它们都拥有相同的《1.战斗至死》这个角色ID。想要将他们合并,也就是让这两个树状结构拥有相同的根。由于我们是按照从左到右的顺序遍历的,所以左边这棵树合并到右边这棵树是最自然的结果。如何做?以《1.战斗至死》举例,我们让它的根的根,等于第二棵树的根的根。
很多人要迷惑了啊,什么根的根的根。一个一个来看。第一个根是上图左侧的《1.战斗至死》的根,也就是《0.一往无前》。第二个根是上图左侧的《0.一往无前》的根,是它自己。第三个根,也就是我们在便利第二个周小董的游戏角色时,遇到的重复元素《1.战斗至死》的根,也就是《3.逍遥自在》。至此,两棵树会合并完成了。
最终状态就是下图的状态。

现在让我们看看剩下两棵树