编辑回应评论:
删除重复函数名称具有误导性,它实际上是试图返回在序列中重复的单词列表,但该结果列表中每个重复项只有一个副本 – user2624236 10 小时前
我暗示了std::sort
+ std::adjacent_find(... std::equal_to<>)
。这是实现的:
template <typename C, typename T = typename C::value_type> std::list<T> adjacent_search(C input)
{
std::sort(begin(input), end(input));
static const auto eq = std::equal_to<T>{};
static const auto neq= std::not2(eq);
std::list<T> dupes;
auto end_streak = begin(input);
auto dupe_at = std::adjacent_find(end_streak, end(input), eq);
for(auto end_streak=begin(input);
(dupe_at = std::adjacent_find(end_streak, end(input), eq)) != end(input);
end_streak = std::adjacent_find(dupe_at, end(input), neq))
{
dupes.insert(dupes.end(), *dupe_at);
}
return dupes;
}
这个实现有几个不错的属性,例如线性扫描和合理的最坏情况行为(例如,如果输入包含单个值的 1000 个重复项,它不会进行 1001 次无用的搜索)。
但是,以下(使用集合)可能要简单得多:
// simple, but horrific performance
template <typename C, typename T = typename C::value_type> std::list<T> simple(C const& input)
{
std::set<T> dupes; // optimization, dupes.find(x) in O(log n)
for (auto it = begin(input); it != end(input); ++it)
{
if ((end(dupes) == dupes.find(*it))) // optimize by reducing find() calls
&& (std::count(it, end(input), *it) > 1))
{
dupes.insert(dupes.end(), *it);
}
}
return {begin(dupes), end(dupes)};
}
这几乎肯定会在较小的集合上表现得更好,因为复制更少(结果除外)。由于在std::count
.
我建议您std::set<T>
直接返回,而不是将其复制到列表中。
这是在 Coliru 上运行Live的测试,显示了两个版本。
原始答案
现在已经过时了,因为它没有做 OP 想要的:
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<std::string> input = { "unsorted", "containing", "optional", "unsorted", "duplicate", "duplicate", "values" };
std::sort(begin(input), end(input));
std::unique_copy(begin(input), end(input), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << "\n";
}
输出:
containing duplicate optional unsorted values
现场观看:http ://coliru.stacked-crooked.com/view?id=f8cc78dbcce62ad276691b6541629a70-542192d2d8aca3c820c7acc656fa0c68