多个集合,取交集
1 Preface
最近在一直采用 go 语言进行项目开发,遇到一个比较有意思的问题:
多个集合,计算交集,哪种计算方法最高效?
假定集合采用 HashMap 来实现,那么每次查询的时间复杂度为 O(1)
考虑最简单的情况,假定有2个集合A和B,A 的元素个数为2, B 的元素个数为10。
计算A和B的交集有 2 个方案:
方案一:先遍历A,在B中查找是否存在,时间复杂度为 2*O(1)
方案二:时间复杂度为 10*O(1)
于是得出结论:
每次遍历最小的集合去计算交集,总的时间复杂度最小。
2 寻找已有的轮子
由于 go 标准库,并不提供 set 数据结构;先尝试用 google 搜索,fatih/set 出镜率比较高。 于是简单看了下交集实现:先求 2 遍并集(Union),真是简单粗暴,果断弃之。(PS 目前这个库已Archive,也不再维护了)
继续尝试在 github 上搜索 go-set,忽然眼前一亮,发现 scylladb
实现了一个(scylladb出品,必属精品); 确认过眼神,正是我想要的。
3 源码实现 (go语言)
下面是 scylladb 的 go-set 实现, 和前面总结的思路一致。
|
|
4 总结
开源的时代,虽然开箱即用,也需要根据实际需求,加以斟酌,寻找真正适合的轮子哈。
5 更上一层楼
Q: 如果是求多个集合的并集(Union)呢?
A: 同样的思路,我们还是要遍历元素较小的集合;
也就是说:我们就把元素最多的那个集合单独拿出来,每次只往里面添加元素即可。