求交集和并集的线性算法
2016-07-19 20:59
281 查看
对于给定的两个集合,使用哈希表可以在线性时间复杂度内得到他们的交集和并集,具体说明如下:
假设有集合A={1, 7, 5, 13, 9, 10, 11}, B={5, 7, 10, 1, 18, 12},
1)求交集,需要得到结果:A∩B={1, 5, 7,10}
思路如下:
①建立一个哈希表(HashTable),其键(KEY)表示集合中数字的值,其值(VALUE)表示集合中数字出现的次数
②遍历集合A,将集合中的每个数字(KEY)插入哈希表,每个数字的出现次数(VALUE)设置为1
③遍历集合B,对于集合中的每个数字:
④遍历哈希表,输出VALUE为2的数字,即得到A和B的交集
2) 求并集,需要得到结果:AUB={1,5,7,9,10,11,12,13,18}
思路如下:
①建立一个哈希表(HashTable),其键(KEY)表示集合中数字的值,其值(VALUE)可以无视;
②遍历集合A,将集合中的每个数字(KEY)插入哈希表 ;
③遍历集合B,对于集合中的每个数字:
④遍历哈希表,输出哈希表中的每个KEY,即为A和B的并集
上面以两个集合为例说明了交集和并集的求法,事实上,上述算法可以很方便的扩展到3个或3个以上的集合的求交集和求并集。另外求并集时,由于哈希表的值(VALUE)部分不需要用到,所以这个数据结构也可以更换为哈希集(HashSet或hash_map\map)。
以上使用map实现,仍然可以改成hash_map或者常见数组实现。
参考资料:
http://akalius.iteye.com/blog/1211726
另外比较好的资料:
http://blog.csdn.net/jie1991liu/article/details/13168255
map或hash_map常见操作:
http://blog.sina.com.cn/s/blog_61533c9b0100fa7w.html
http://blog.chinaunix.net/uid-26548237-id-3800125.html
假设有集合A={1, 7, 5, 13, 9, 10, 11}, B={5, 7, 10, 1, 18, 12},
1)求交集,需要得到结果:A∩B={1, 5, 7,10}
思路如下:
①建立一个哈希表(HashTable),其键(KEY)表示集合中数字的值,其值(VALUE)表示集合中数字出现的次数
②遍历集合A,将集合中的每个数字(KEY)插入哈希表,每个数字的出现次数(VALUE)设置为1
③遍历集合B,对于集合中的每个数字:
如果哈希表中已经存在该数字,将对应的VALUE改为2; 如果哈希表中不存在该数字,忽略;
④遍历哈希表,输出VALUE为2的数字,即得到A和B的交集
2) 求并集,需要得到结果:AUB={1,5,7,9,10,11,12,13,18}
思路如下:
①建立一个哈希表(HashTable),其键(KEY)表示集合中数字的值,其值(VALUE)可以无视;
②遍历集合A,将集合中的每个数字(KEY)插入哈希表 ;
③遍历集合B,对于集合中的每个数字:
如果哈希表中已经存在该数字,忽略; 如果哈希表中不存在该数字,将这个数字插入哈希表;
④遍历哈希表,输出哈希表中的每个KEY,即为A和B的并集
上面以两个集合为例说明了交集和并集的求法,事实上,上述算法可以很方便的扩展到3个或3个以上的集合的求交集和求并集。另外求并集时,由于哈希表的值(VALUE)部分不需要用到,所以这个数据结构也可以更换为哈希集(HashSet或hash_map\map)。
#include <stdio.h> #include <stdlib.h> #include <list> #include <map> //求交集 void interSection(list<int> &A,list<int> &B,list<int>& C) { map<int,int> mp; for (list<int>::iterator it=A.begin(); it!=A.end(); it++){ mp[*it] = 1; } for (list<int>::iterator it=B.begin(); it!=B.end(); it++){ if (mp.find(*it) != mp.end()){ mp[*it] += 1; } } for (map<int,int>::iterator it=mp.begin(); it!=mp.end(); it++){ //printf("%d-%d\n",it->first,it->second); if (it->second > 1){ C.push_back(it->first); } } return; } //求并集 void unionList(list<int> &A,list<int> &B,list<int>& C) { map<int,int> mp; for (list<int>::iterator it=A.begin(); it!=A.end(); it++){ mp[*it] = 1; } for (list<int>::iterator it=B.begin(); it!=B.end(); it++){ mp[*it] = 1; } for (map<int,int>::iterator it=mp.begin(); it!=mp.end(); it++){ //printf("%d-%d\n",it->first,it->second); if (it->second == 1){ C.push_back(it->first); } } return; } int main() { list<int> L,P; for (int i=0; i<10; i++){ L.push_back(i+1); P.push_back(i+6); } list<int> a; interSection(L,P,a); for (list<int>::iterator it=a.begin(); it!=a.end(); it++){ printf("%d ",*it); } a.clear(); printf("\n"); unionList(L,P,a); for (list<int>::iterator it=a.begin(); it!=a.end(); it++){ printf("%d ",*it); } system("pause"); return 0; }
以上使用map实现,仍然可以改成hash_map或者常见数组实现。
参考资料:
http://akalius.iteye.com/blog/1211726
另外比较好的资料:
http://blog.csdn.net/jie1991liu/article/details/13168255
map或hash_map常见操作:
http://blog.sina.com.cn/s/blog_61533c9b0100fa7w.html
http://blog.chinaunix.net/uid-26548237-id-3800125.html
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法