面试题引入
问题描述:
假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友…),
则认为他们属于同一个朋友圈,
请写程序求出这n个人里一共有多少个朋友圈。
假如:n = 5, m = 3, r = { {1 , 2} , {2 , 3} ,{4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,
则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。
最后请分析所写代码的时间、空间复杂度。评分会参考代码的正确性和效率。
问题分析
这道题本质上是其实是求解一个图中有多少无向连通分量的问题,如下图:
上图1,2,3,4,5可以看作是一个图中的节点, r = {
{1 , 2} , {2 , 3} ,{4 , 5}}是这个图中顶点与顶点之间的连接关系。我们要求构成朋友圈的个数,只要求图中连通图的个数即可,如本题中的链接关系,我们可知道图中最小连通图的个数为2,所以构成朋友圈的个数为2。
虽然这种解法可以得到问题的最终结果但是这种解法需要遍历整个图,如果是邻接表来表示图,那么遍历整个图的时间复杂度为O(N*N),还有建立图等问题也有时间复杂度的消耗,所以总的来说这不是面试官喜欢的解法。
时间复杂度为O(N)的解法
本题中r = {
{1 , 2} , {2 , 3} ,{4 , 5}}可以看成是一个大集合,里面的各个朋友关系可以看成是这个大集合中的子集,当两个子集中有相同的元素,可以把这两个子集合并成一个子集,最后我们只需要统计出大集合中子集的个数就能知道一共有多少个朋友圈了。
在这里向大家介绍一种数据结构可以很好的解决这个问题:
这种结构叫做并查集,它实际上是一个数组数