C++/STL 我应该使用哪种算法来检查容器是否有重复项?

C++/STL which algorithm should I use to check if a container has duplicates?

本文关键字:是否 检查 我应该 STL 算法 C++      更新时间:2023-10-16

是否有任何STL算法可以判断容器是否具有重复的元素(使用operator==或给定的谓词(?

让我们考虑这两个向量:

std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 1, 2, 1 };

我期待这样的函数:

std::is_exclusive( v1.begin(), v1.end() ); // returning true
std::is_exclusive( v2.begin(), v2.end() ); // returning false

有这么简单的功能吗?我找不到任何(找到std::unique,但这修改了向量...

注意:我不是在问如何"检查容器是否有重复项",我知道我该怎么做(基本上,我可以做( std::set<int>( v1.begin(), v1.end() ).size() == v1.size() )并且可能存在许多其他选项。我问是否有一个 STL 算法函数可以以更智能的方式做到这一点,因为我很惊讶我找不到任何......

实现类似 STL 的is_exclusive模板函数的一种方法是使用std::unordered_map来保持范围内元素的计数。只要任何元素的计数超过 1,函数模板就可以返回false

#include <unordered_map>
template<typename ForwardIt>
bool is_exclusive(ForwardIt first, ForwardIt last) {
std::unordered_map<typename ForwardIt::value_type, unsigned> count;
for (auto it = first; it != last; ++it)
if (++count[*it] > 1)
return false;
return true;
}

对于您的示例:

int main() {
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 1, 2, 1 };

assert(is_exclusive(v1.begin(), v1.end()));
assert(!is_exclusive(v2.begin(), v2.end()));
}

STL是关于效率和普遍性的。似乎没有通用且有效的方法来检查容器是否有重复项而不对其进行修改。因此,难怪STL中不存在这样的算法。

我唯一能做的就是 https://en.cppreference.com/w/cpp/algorithm/adjacent_find,但它需要对元素进行排序,因为它将签入相邻元素。

编辑:

没有 stl 算法可以按照您的要求做到这一点,另一种选择是使用 std::any_of。

一种方法是使用 std::set。

将向量复制到集合中,并比较元素的数量是否相同。

如果是,则没有重复项,如果否,您可以猜测重复项的数量。

#include <iostream>
#include <iterator>
#include <vector>
#include <set>
int has_duplicate(const std::vector<int> & v)
{
std::set<int> s(v.begin(), v.end());
return v.size() - s.size();
}
int
main()
{
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 1, 2, 1 };
std::cout << has_duplicate(v1) << std::endl;
std::cout << has_duplicate(v2) << std::endl;
}

对于 v1,输出为 0 ->则没有重复项 对于 v2,输出为 1 ->您有一个副本

该算法的成本为 O(N*log(N((