Так как я не был доволен предыдущим ответом, вот мой сегодня.Ваш начальный вопрос не упоминает, насколько велик ваш вектор.Предположим, ваш std::vector<>
очень большой и имеет очень мало дубликатов (почему бы и нет?).Это означает, что использование другого контейнера (например, std::set<>
) в основном дублирует потребление памяти.Зачем вам это делать, поскольку ваша цель - просто считать не дубликат.
Мне нравится @Flame
ответ, но я не очень доволен звонком на std::unique
.Вы потратили много времени на тщательную сортировку своего вектора, а затем просто отбросили отсортированный массив, в то время как впоследствии вы могли бы повторно использовать его.
Я не смог найти ничего действительно элегантного в библиотеке STD, поэтому вот мойпредложение (смесь std::transform
+ std::abs
+ std :: sort , но без последующего касания отсортированного массива).
// count the number of distinct absolute values among the elements of the sorted container
template<class ForwardIt>
typename std::iterator_traits<ForwardIt>::difference_type
count_unique(ForwardIt first, ForwardIt last)
{
if (first == last)
return 0;
typename std::iterator_traits<ForwardIt>::difference_type
count = 1;
ForwardIt previous = first;
while (++first != last) {
if (!(*previous == *first) ) ++count;
++previous;
}
return count;
}
Бонусный пункт работает с прямым итератором:
#include <iostream>
#include <list>
int main()
{
std::list<int> nums {1, 3, 3, 3, 5, 5, 7,8};
std::cout << count_unique( std::begin(nums), std::end(nums) ) << std::endl;
const int array[] = { 0,0,0,1,2,3,3,3,4,4,4,4};
const int n = sizeof array / sizeof * array;
std::cout << count_unique( array, array + n ) << std::endl;
return 0;
}