前几天在csdn上看到百度一道笔试题:
百度全体员工玩分组游戏,前面五分钟大家分头找队友,并将每个人找到的队友信息汇报给主持人,如果A和B是队友,B和C是队友,那么A和C也是队友;接着主持人不断地随机抽取两个人,希望判断二者是否为队友。请设计一个计算机程序辅助主持人判断两个人是否为队友,说明程序的关键算法,不需要代码实现。例如:<小明,小王>,<小军,小王>,<小丽,小李>是队友,那么小军和小明是队友,小军和小丽不是队友。
开始我的想法是:
为每个人维护一个队友队列,比如<小明,小王>,
小明->小王
然后<小军小王>,遍历队列如果还有这两个人中的一个加入队列,变化
小明->小王->小军
对<小丽,小李>建立新队列
判断两个人是不是队友,就得遍历每个队列,看这两个人是不是在一个同队列中。
这样的复杂度明显比较高,因为每次查找队列比较麻烦,合并的话还好。那个帖子的讨论中有人说用并查集,于是百度了一下,确实比较好。其实这个题还是从一道acm习题改过来的。
说一下并查集的定义吧。
在一些应用问题中,我们需要划分n个不同的元素成若干组,每一组的元素构成一个集合。这种问题的一个解决办法是,在开始时,让每个元素自成一个单元素集合,然后按一定顺序将属于同一组的元素所在的集合合并。其间要反复用到查找一个元素在哪一个集合的运算。适合于描述这类问题的抽象数据类型称为并查集。
有n个人(1..n),如果i和j是亲戚,j和k是亲戚,那么j和k也是亲戚,题目给定n各人的m对亲戚关系,然后提出q各问题,问你某两个人是不是亲戚。
下面是我看了并查集之后写的代码。用树表示集合的,其实就是数组,i下标对应是其parent节点。
输入: 8
10,7
2,4
5,7
1,3
8,9
1,2
5,6
2,3
3
3,4
1,5
2,3
输出
YES
No
YES
和其他并查集的应用相比,这个还算比较简单的了。由此可见这些算法题一般比较偏ACM,所以系统的学习一下ACM的算法还是有帮助的,虽然咱不去参加acm的比赛,前几天网易有道难题也是acm的。
所以继续努力吧。