并查集(UnionFindSet)
生活随笔
收集整理的這篇文章主要介紹了
并查集(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都加到根節點里面去,然后非根節點存上根節點的下標,這樣遍歷數組時,為負數的就是根,負幾那個朋友圈就有幾個人,那幾個人就是存這個根下標的元素。
具體實現如下:
#include<iostream>
#include<cassert>
using namespace std;
int?FindRoot(int?*set,int?child)
{
????assert(set);
????while(set[child]?>=?0)
????{
????????child?=?set[child];
????}
????return child;
}
void Combine(int?*set,int?root1,int?root2)
{
????assert(set);
????set[root1]?+=?set[root2];
????set[root2]?=?root1;
}
int?FindFrinedsCircle(int?n,int?m,int?r[][2])
{
????assert(r);
????int?*set?=?new?int(n);
????memset(set,-1,sizeof(int)*n);
????for(int?i?=?0;i?<?m;++i)
????{
????????int?first?=?r[i][0];
????????int?second?=?r[i][1];
????????int?root1?=?FindRoot(set,first);
????????int?root2?=?FindRoot(set,second);
????????if(root1?!=?root2)
????????{
????????????Combine(set,root1,root2);
????????}
????}
????int?count?=?0;
????for(int?i?=?0;i?<?n;++i)
????{
????????if(set[i]?<?0?)
????????{
????????????count++;
????????}
????}
????return count;
}
int?main()
{
????int?r[][2]?=?{{1?,?2}?,?{2?,?3}?,?{4?,?5}};
????cout<<FindFrinedsCircle(5,3,r)<<endl;
????return 0;
}
朋友圈(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都加到根節點里面去,然后非根節點存上根節點的下標,這樣遍歷數組時,為負數的就是根,負幾那個朋友圈就有幾個人,那幾個人就是存這個根下標的元素。
具體實現如下:
總結
以上是生活随笔為你收集整理的并查集(UnionFindSet)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 条款11 在operator=中处理“自
- 下一篇: IDF实验室-图片里的英语