可能重复:
How to make elements of vector unique? (remove non adjacent duplicates)
是否有任何标准算法作为STL算法的一部分提供,可以在保留顺序的同时从阵列中删除重复项。例如,如果删除重复项后我有int a[] = {2,1,3,1,4,2};
之类的数组,那么它应该是a[] = {2,1,3,4};
。我无法使用std::unique
,因为数组未排序。其他解决方案,例如将其插入std::set
我会丢失顺序,因为元素将被排序。我还可以使用其他任何算法组合,或者我必须编写自己的算法吗?
答案 0 :(得分:6)
没有标准算法,但实施起来相当容易。原则是保留到目前为止看到的std::set
个项目,并在复制到新的向量或数组时跳过重复项。这在O(n lg n)时间和O(n)存储器中操作。如果你正在使用C ++ 0x,那么你可以使用std::unordered_set
为看到的项目设置将其缩短到O(n)时间;这使用哈希表而不是二叉树,应该更快。
答案 1 :(得分:3)
由于问题相对“复杂”,我不会尝试仅通过使用标准算法强制解决方案(因为没有特殊的算法来解决您的问题。您可能使用remove_if,find和bind2nd或东西)。 为了自己实现算法,你基本上有两个选择,通常的内存与速度权衡。 第一种解决方案是迭代向量并搜索并删除当前项的重复项。这是cpu密集型方法。 可能更快的方法是创建第二个向量(与第一个向量相同以最小化内存重新分配)并将找到的项存储在那里。然后,对于原始矢量的每次迭代,仅需要搜索较短的第二矢量以找出是否应该删除当前项目。 第一种方法适用于每个迭代器,而第二种方法仅限于随机访问迭代器。 以下是实施:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
template<typename T>
void remove_duplicates_ordered_mem_intensive(T &container)
{
std::vector<typename T::value_type> items;
items.reserve (container.size());
typename T::iterator i = container.begin();
while (i != container.end())
{
if (find (items.begin(), items.end(), *i) != items.end())
i = container.erase(i);
else
{
items.push_back(*i);
++i;
}
}
}
template<typename T>
void remove_duplicates_ordered_slow(T &container)
{
typename T::iterator i = container.begin();
while (i != container.end())
{
typename T::iterator f = i;
++f;
while (f != container.end())
{
if (*f == *i)
f = container.erase(f);
else
++f;
}
++i;
}
}
int main ()
{
vector<int> v;
v.push_back (2);
v.push_back (1);
v.push_back (3);
v.push_back (1);
v.push_back (4);
v.push_back (2);
cout << "Old:\n";
for (vector<int>::const_iterator i = v.begin(); i != v.end(); ++i)
cout << *i << endl;
vector<int> a (v), b (v);
remove_duplicates_ordered_mem_intensive (a);
remove_duplicates_ordered_slow (b);
cout << "\nRemoved duplicates with intensive memory usage:\n";
for (vector<int>::const_iterator i = a.begin(); i != a.end(); ++i)
cout << *i << endl;
cout << "\nRemoved duplicates somewhat slower, without copying:\n";
for (vector<int>::const_iterator i = b.begin(); i != b.end(); ++i)
cout << *i << endl;
}
答案 2 :(得分:1)
从数组中删除重复项
这在技术上是不可能的,因为数组不能改变大小。