您的位置:首页 > 其它

消除集合中的重复元素

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++ 代码(假设它们的元素都是字符元素):

#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;
}
运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: