【问题标题】:Checking for duplicates in a vector [duplicate]检查向量中的重复项[重复]
【发布时间】:2010-05-18 19:56:09
【问题描述】:

可能重复:
Determining if an unordered vector<T> has all unique elements

我必须检查向量是否有重复项。解决此问题的最佳方法是什么:

我取第一个元素,将它与向量中的所有其他元素进行比较。然后取下一个元素并执行相同的操作,依此类推。

这是最好的方法,还是有更有效的方法来检查重复数据?

【问题讨论】:

  • 可以修改矢量吗?如果没有,你有内存来分配副本吗?
  • "...取下一个元素并做同样的事情..." 对于它的价值,当您查看第二个元素时,您可以忽略第一个元素 ;-) (当您'正在查看第三个元素,可以忽略前两个等)

标签: c++


【解决方案1】:

如果你的向量是一个 STL 容器,解决方法很简单:

std::sort(myvec.begin(), myvec.end());
std::erase(std::unique(myvec.begin(), myvec.end()), myvec.end());

根据 cppreference (https://en.cppreference.com/w/cpp/algorithm/unique),元素被移动,使得从myvec.begin() 到返回值std::unique 的值都是唯一的。 std::unique 返回的迭代器后面的元素是未指定的(在我见过的每个用例中都是无用的)所以使用 std::vector&lt;A&gt;::erasestd::vector&lt;A&gt; 中删除它们。

【讨论】:

  • 为了澄清,重复项不会移动到范围的末尾;它们只是从范围的前面移除。 std::unique() 返回的新结尾之后的元素的值未指定。如果只想测试范围是否不包含重复项,std::adjacent_find() 比使用std::unique() 效率更高。
  • 你是对的。 Std::unique 将所有唯一元素放在首位,并没有指定容器的其余部分会发生什么。然而,最重要的是要记住你应该使用返回的迭代器,而不是假设你的容器只包含唯一的元素。您必须手动清理容器的尾部。
【解决方案2】:

使用hash table 插入每个元素。在插入元素之前,请检查它是否已经存在。如果是,你有自己的副本。这是O(n)平均,但最坏的情况与您当前的方法一样糟糕。

或者,您可以使用setO(n log n) 最坏的情况下执行相同的操作。这与排序解决方案一样好,只是它不会更改元素的顺序(虽然因为您创建了一个集合,但会使用更多内存)。

另一种方法是将您的向量复制到另一个向量,对其进行排序并检查那里的相邻元素。我不确定这是否比集合解决方案更快,但我认为排序比集合使用的平衡搜索树增加的开销更少,因此在实践中应该更快。

当然,如果你不关心保持元素的原始顺序,只需对初始向量进行排序即可。

【讨论】:

  • 不如排序解决方案“好”。它是相同的 big-O 运行时顺序,但是对向量进行排序的常数因子(保证其元素在内存中是连续的)将明显小于使用集合的算法。如果它的速度是原来的两倍,我一点也不感到惊讶。无论如何+1。我认为你有最好的答案。
  • @A. Levy:是的,我提到了另一种方法。
  • 基数排序甚至比 O(n log n) 还要快。 en.wikipedia.org/wiki/Radix_sort
  • @Mark Ransom,基数排序很少适用。
  • @avakar,是的,但很少与从不相同。我认为是因为没有库实现比它应该被遗忘的频率更高。
【解决方案3】:

如果您不关心偶尔的误报,您可以使用Bloom Filter 来检测集合中可能的重复项。如果不能接受误报,请获取未通过过滤器的值并对其进行第二次检测。失败值的列表应该相当小,尽管需要根据完整的输入来检查它们。

【讨论】:

    【解决方案4】:

    排序然后比较相邻元素是要走的路。排序需要 O(n log n) 比较,然后是额外的 n-1 来比较相邻元素。

    问题中的方案将进行 (n^2)/2 次比较。

    【讨论】:

      【解决方案5】:

      您也可以使用 binary_search。

      这里有两个很好的例子可以帮助你:

      http://www.cplusplus.com/reference/algorithm/binary_search/

      http://www.cplusplus.com/reference/algorithm/unique_copy/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-16
        • 1970-01-01
        • 1970-01-01
        • 2019-01-28
        • 1970-01-01
        • 2016-10-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多