小米麵試題--朋友圈問題
阿新 • • 發佈:2019-02-15
假如已知有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個朋友圈。
這個題其實考察了資料結構並查集問題;
並查集:將N個不同的元素分成一組不相交的集合。
開始時,每個元素就是一個集合,然後按規律將兩個集合進行合併。
演算法思想:定義大小為n的陣列,數組裡邊開始存的都是-1,表示每個位置都是一個獨立的朋友圈,
然後1和2是好友 讓下標1的位置加-1,然後依次把朋友之間的關係存入這個數組裡邊。
#pragma once
class UnionFindSet
{
public:
UnionFindSet(size_t size)
{
_ufs.resize(size, -1);
}
int Findroot(int x)
{
int root = x;
while (_ufs[root] >= 0)
{
root = _ufs[root];
}
return root;
}
void Union(int x1, int x2)
{
int root1 = Findroot(x1);
int root2 = Findroot(x2);
if (root1 != root2)
{
_ufs[root1] += _ufs[root2];
_ufs[root2] = root1;
}
}
bool IsInOneSet(int x1, int x2)
{
return Findroot(x1) == Findroot(x2);
}
size_t GetSetSize()
{
int count = 0;
for (size_t i = 0; i < _ufs.size(); i++)
{
if (_ufs[i] < 0)
count++;
}
return count;
}
private:
vector<int> _ufs;
};
int friends(int n, int m, int r[][2])
{
UnionFindSet ufs(n + 1);
for (size_t i = 0; i < m; i++)
{
ufs.Union(r[i][0], r[i][1]);
}
return ufs.GetSetSize() - 1; //0沒資料
}
void TestUnionFindSet()
{
int n = 5;
const int m = 3;
int r[m][2] = { { 1, 2 }, { 2, 3 }, { 4, 5 } };
cout << "朋友圈有幾個?" << friends(n, m, r) << endl;
}