并查集(UnionFindSet)

小米的校招题:
朋友圈(25分)
假如已知有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个朋友圈。
最后请分析所写代码的时间、空间复杂度。评分会参考代码的正确性和效率。
C/C++:
int friends(int n , int m , int* r[]);

思路:此题可以用并查集来解决,并查集数组刚开始里面存的都是-1,把每个圈子看成一个树,把其非根结点的-1都加到根节点里面去,然后非根节点存上根节点的下标,这样遍历数组时,为负数的就是根,负几那个朋友圈就有几个人,那几个人就是存这个根下标的元素。
具体实现如下:


  1. #include<iostream>
  2. #include<cassert>
  3. using namespace std;

  4. int FindRoot(int *set,int child)
  5. {
  6.     assert(set);
  7.     while(set[child] >= 0)
  8.     {
  9.         child = set[child];
  10.     }
  11.     return child;
  12. }
  13. void Combine(int *set,int root1,int root2)
  14. {
  15.     assert(set);
  16.     set[root1] += set[root2];
  17.     set[root2] = root1;
  18. }
  19. int FindFrinedsCircle(int n,int m,int r[][2])
  20. {
  21.     assert(r);

  22.     int *set = new int(n);
  23.     memset(set,-1,sizeof(int)*n);

  24.     for(int i = 0;< m;++i)
  25.     {
  26.         int first = r[i][0];
  27.         int second = r[i][1];

  28.         int root1 = FindRoot(set,first);
  29.         int root2 = FindRoot(set,second);

  30.         if(root1 != root2)
  31.         {
  32.             Combine(set,root1,root2);
  33.         }
  34.     }
  35.     int count = 0;
  36.     for(int i = 0;< n;++i)
  37.     {
  38.         if(set[i] < 0 )
  39.         {
  40.             count++;
  41.         }
  42.     }
  43.     return count;
  44. }
  45. int main()
  46. {
  47.     int r[][2] = {{, 2} , {, 3} , {, 5}};
  48.     cout<<FindFrinedsCircle(5,3,r)<<endl;
  49.     return 0;
  50. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值