Что подразумевается под "столь же эффективным, как std :: unique"? Эффективен с точки зрения времени выполнения, времени разработки, использования памяти или как?
Как отмечали другие, для std :: unique требуется отсортированный ввод, который вы не предоставили, поэтому с самого начала это не честный тест.
Лично я бы хотел, чтобы std :: map делал всю мою работу за меня. У этого есть много свойств, которые мы можем использовать для максимальной элегантности / краткости. Он сохраняет свои элементы отсортированными, и оператор [] вставит нулевое значение, если ключ еще не существует. Используя эти свойства, мы можем сделать это в две или три строки кода и при этом достичь разумной сложности во время выполнения.
По сути, мой алгоритм таков: для каждого элемента в векторе увеличивайте на единицу запись карты, указав значение этого элемента. После этого просто пройдитесь по карте, выводя любой ключ, значение которого больше 1. Не может быть проще.
#include <iostream>
#include <vector>
#include <map>
void
output_sorted_duplicates(std::vector<int>* v)
{
std::map<int, int> m;
// count how many of each element there are, putting results into map
// map keys are elements in the vector,
// map values are the frequency of that element
for (std::vector<int>::iterator vb = v->begin(); vb != v->end(); ++vb)
++m[*vb];
// output keys whose values are 2 or more
// the keys are already sorted by the map
for (std::map<int, int>::iterator mb = m.begin(); mb != m.end(); ++mb)
if ( (*mb).second >= 2 )
std::cout << (*mb).first << " ";
std::cout << std::endl;
}
int main(void)
{
int initializer[] = { 4, 4, 1, 2, 3, 2, 3 };
std::vector<int> data(&initializer[0], &initializer[0] + 7);
output_sorted_duplicates(&data);
}
janks@phoenix:/tmp$ g++ test.cc && ./a.out
2 3 4
Итак, мы посещаем каждый элемент в вашем векторе один раз, а затем каждый элемент на моей карте, где количество элементов на моей карте в худшем случае не больше, чем ваш вектор. Недостатки моего решения - намного больше места для хранения, чем решения, которые предполагают перестановку вашего вектора на месте. Преимущества, однако, очевидны. Он невероятно короткий и простой, он, безусловно, правильный, без необходимости в большом тестировании или проверке кода, и обладает приемлемыми характеристиками производительности.
Создание моей функции как шаблона и приведение его в действие в диапазонах в стиле STL, а не только в векторах целых, оставлено в качестве упражнения.