小米面试题——并查集(关于朋友圈问题)

本文介绍了一种利用并查集算法解决朋友圈分组问题的方法。通过实例详细展示了如何运用并查集进行好友关系的合并与查询,最终计算出朋友圈的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   假如已知有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属于另一个朋友圈,结果为两个朋友圈


在处理这道题的时候,我用的是并查集来处理的

什么是并查集:

       并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。在一些有N个元素的集合应用问题中,通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中


下面来看看关键代码的实现以及图解

<strong><span style="font-size:18px;">	int FindRoot(int x)
	{
		if (_set[x] >= 0)
		{
			x = _set[x];
		}
		return x;
	}</span></strong>

<strong><span style="font-size:18px;">	void Union(int x1,int x2)
	{
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);

		if (root1 != root2)
		{
			_set[root1] += _set[root2];
			_set[root2] = root1;
		}
	}</span></strong>



下面是全部代码及其测试

“test.cpp”

<strong><span style="font-size:18px;">#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <assert.h>

class UnionFindSet
{
public:
	//构造函数
	UnionFindSet(int n)
		:_n(n)
		,_set(new int[n])
	{
		//初始化_set数组,全部初始化为-1
		memset(_set,-1,sizeof(int)*n);
	}
	void Union(int x1,int x2)
	{
		int root1 = FindRoot(x1);
		int root2 = FindRoot(x2);

		if (root1 != root2)
		{
			_set[root1] += _set[root2];
			_set[root2] = root1;
		}
	}
	int Count()
	{
		int count = 0;
		for (size_t i = 0;i < _n;i++)
		{
			if (_set[i] < 0)
			{
				count++;
			}
		}
		return count-1;//0的位置一开始就初始化成-1,0的位置不用
		               //故_set[0]为负数不属于一个朋友圈
	}
private:
	int FindRoot(int x)
	{
		if (_set[x] >= 0)
		{
			x = _set[x];
		}
		return x;
	}
protected:
	int* _set;//设置一个数组存放值
	int _n;
};

int Friend(int n,int m,int r[][2])
{
	assert(r);
	UnionFindSet ufs(n+1);//0的位置不用
	for (size_t i = 0;i < m;i++)
	{
		int r1 = r[i][0];
		int r2 = r[i][1];
		ufs.Union(r1,r2);
	}
	
	return ufs.Count();
}
void Test1()
{
	int r[3][2] = {{1,2},{2,3},{4,5}};//n=总人数,m=多少对好友关系
	cout<<"朋友圈?"<<Friend(5,3,r)<<endl;
}
void Test2()
{
	int r[][2] = {{1,2},{2,3},{4,5},{5,9},{6,2},{7,8}};//n=总人数,m=多少对好友关系
	cout<<"朋友圈?"<<Friend(9,6,r)<<endl;
}
int main()
{
	Test1();
	//Test2();
	system("pause");
	return 0;
}</span></strong>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值