消除集合中的重复元素
2016-03-27 22:56
337 查看
给定一个含有重复元素的集合 B,现要消除集合 B 中的重复元素,相同元素只保留一个。也就是说对一个非纯集合 B,构造集合 A 使得集合 A 中只包含集合 B 中所有值不相同的数据元素。
我们先看一个和上述问题类似的问题:对于现有的两个集合 A 和 B,求一个新的集合 A = A
∪ B,即求两个集合的并集。
假设集合 A 和 B 中存放的都是字符元素,要求 A 和 B 的并集,我们可以依次取出集合 B 中的每个元素 b 和集合 A 中的元素作比较,若 A 中已经存在元素
b 则不用将其插入到 A 中,若 A 中不存在元素 b 则将其插入 A 中。直到B中的所有元素都比较完并进行处理之后返回集合 A。因此,我们可以写出求两个集合 A 和 B 的并集的 C++ 代码(假设它们的元素都是字符元素):
![](http://img.blog.csdn.net/20160327221835873)
解决了上面求并集的问题,那么消除集合 B 中的重复元素就简单了,我们只要首先初始化集合 A 为空集即可,之后的操作和求并集的操作完全相同。
但是对于上面的操作,从代码中可以看出有两层 for 循环,因此其时间复杂度为 O(n^2)。
现在我们考虑先对集合 B 中的元素按元素值从小到大进行排序,排序后值相同的元素必相邻。因为集合 A 开始时为空集,则取出集合 B 中的第一个元素直接插入 A 中。之后依次取出 B 中的元素,其值和 A 中的最后一个元素值相比只有大于和相等这两种情况,因此只需和 A 中最后一个元素比较即可,而不用对 A 中元素进行从头至尾的查询。这样一来只用一次循环就可以了,其时间复杂度为
O(n),而排序的时间复杂度我们可以保证为 O(nlog n),因而总的时间复杂度为 O(nlog n),相比 O(n^2) 要小了一个数量级。其
C++ 代码如下:
我们先看一个和上述问题类似的问题:对于现有的两个集合 A 和 B,求一个新的集合 A = A
∪ B,即求两个集合的并集。
假设集合 A 和 B 中存放的都是字符元素,要求 A 和 B 的并集,我们可以依次取出集合 B 中的每个元素 b 和集合 A 中的元素作比较,若 A 中已经存在元素
b 则不用将其插入到 A 中,若 A 中不存在元素 b 则将其插入 A 中。直到B中的所有元素都比较完并进行处理之后返回集合 A。因此,我们可以写出求两个集合 A 和 B 的并集的 C++ 代码(假设它们的元素都是字符元素):
#include <iostream> #include <vector> using namespace std; void Union(vector<char>& va, vector<char> vb) { vector<char>::iterator ita, itb; for (itb = vb.begin(); itb != vb.end(); ++itb) { for (ita = va.begin(); ita != va.end(); ++ita) { if (*itb == *ita) { break; } } if (ita == va.end()) { va.push_back(*itb); } } } int main() { vector<char> va = { 'h', 'y', 'a', 'f', 'c', 'z', 'b' }; vector<char> vb = { 'v', 'a', 'c', 'e', 'd' }; Union(va, vb); for (vector<char>::iterator ita = va.begin(); ita != va.end(); ++ita) { cout << *ita << " "; } cout << endl; return 0; }其运行结果如下:
解决了上面求并集的问题,那么消除集合 B 中的重复元素就简单了,我们只要首先初始化集合 A 为空集即可,之后的操作和求并集的操作完全相同。
但是对于上面的操作,从代码中可以看出有两层 for 循环,因此其时间复杂度为 O(n^2)。
现在我们考虑先对集合 B 中的元素按元素值从小到大进行排序,排序后值相同的元素必相邻。因为集合 A 开始时为空集,则取出集合 B 中的第一个元素直接插入 A 中。之后依次取出 B 中的元素,其值和 A 中的最后一个元素值相比只有大于和相等这两种情况,因此只需和 A 中最后一个元素比较即可,而不用对 A 中元素进行从头至尾的查询。这样一来只用一次循环就可以了,其时间复杂度为
O(n),而排序的时间复杂度我们可以保证为 O(nlog n),因而总的时间复杂度为 O(nlog n),相比 O(n^2) 要小了一个数量级。其
C++ 代码如下:
#include <iostream> #include <vector> #include <algorithm> using namespace std; void purge(vector<char>& va, vector<char> vb) { sort(vb.begin(), vb.end()); vector<char>::iterator itb; for (itb = vb.begin(); itb != vb.end(); ++itb) { if (va.empty() || *itb != *(va.end() - 1)) { va.push_back(*itb); } } } int main() { vector<char> va; vector<char> vb = { 'v', 'a', 'c', 'v', 'd', 'd', 'c', 'm', 'w', 'v' }; // 排序后为 accddmvvvw purge(va, vb); for (vector<char>::iterator ita = va.begin(); ita != va.end(); ++ita) { cout << *ita << " "; } cout << endl; return 0; }运行结果如下:
相关文章推荐
- 如何理解ip路由和操作linux的路由表
- 20145101《Java程序设计》第4周学习总结
- Delphi XE Seattle update1 调试iOS 9.3程序时,不能用真机调试的问题
- 敏捷开发方法综述
- SQL语句删除重复数据
- 忘记了Linux账户密码怎么办?
- javascript的正则表达式
- linux上安装mysql
- New York city
- 第五周作业
- CentOS网络配置四个方式
- Activity启动模式完全解读-更新中
- zookeeper实现namenode的高可用(HA)(第三篇)
- TCP与UDP两种协议的区别
- DHCP中继各种组网环境配置
- POJ3635 Full Tank?(最短路+DP)
- java接口 学习
- PAT-1013. 数素数 (20)
- Java基础------知识点整理(五)-----多态
- 【应用】在线文件管理