Chinaunix首页 | 论坛 | 博客
  • 博客访问: 259858
  • 博文数量: 84
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 927
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-06 23:00
个人简介

growing

文章分类

全部博文(84)

文章存档

2017年(6)

2016年(61)

2015年(17)

我的朋友

分类: C/C++

2016-05-13 13:26:07

 小米的校招题:
朋友圈(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;i < 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;i < 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] = {{1 , 2} , {2 , 3} , {4 , 5}};
  48.     cout<<FindFrinedsCircle(5,3,r)<<endl;
  49.     return 0;
  50. }



阅读(1501) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~