Для этого вам необходимо отсортировать векторный. Используйте для этого std::sort.
std::lower_bound находит первый элемент, который больше или равен данному элементу. (элементы должны быть, по крайней мере, частично упорядочены)
Оттуда вы повторяете, пока у вас есть последовательные элементы.
Работа с дубликатами: Один из способов - это то, как я пошел: рассмотрим последовательные и равные элементы при итерации. Другой подход заключается в добавлении предпосылки, что вектор/диапазон содержит уникальные элементы. Я выбрал первое, потому что он избегает стирания элементов.
Вот как вы устранения дубликатов из отсортированного вектора:
v.erase(std::unique(v.begin(), v.end()), v.end());
Моя реализация:
// finds the first missing element in the vector v
// prerequisite: v must be sorted
auto firstMissing(std::vector<int> const &v, int elem) -> int {
auto low = std::lower_bound(std::begin(v), std::end(v), elem);
if (low == std::end(v) || *low != elem) {
return elem;
}
while (low + 1 != std::end(v) &&
(*low == *(low + 1) || *low + 1 == *(low + 1))) {
++low;
}
return *low + 1;
}
И обобщенная версия:
// finds the first missing element in the range [first, last)
// prerequisite: the range must be sorted
template <class It, class T = decltype(*std::declval<It>())>
auto firstMissing(It first, It last, T elem) -> T {
auto low = std::lower_bound(first, last, elem);
if (low == last || *low != elem) {
return elem;
}
while (std::next(low) != last &&
(*low == *std::next(low) || *low + 1 == *std::next(low))) {
std::advance(low, 1);
}
return *low + 1;
}
Тестовый пример:
int main() {
auto v = std::vector<int>{13, 8, 3, 6, 10, 1, 7, 7, 7, 0};
std::sort(v.begin(), v.end());
for (auto n : {-2, 0, 5, 6, 20}) {
cout << n << ": " << firstMissing(v, n) << endl;
}
return 0;
}
Результат:
-2: -2
0: 2
5: 5
6: 9
20: 20
Примечание о сортировке: Из комментариев ор, он искал решение, которое не будет изменять вектор.
Вы должны отсортировать векторное изображение для эффективного решения. Если изменение вектора не является вариантом, вы можете создать копию и работать над ней. не
Если вы одержимы не сортировка, есть решение перебора (очень неэффективно - O (N^2)):
auto max = std::max_element(std::begin(v), std::end(v));
if (elem > *max) {
return elem;
}
auto i = elem;
while (std::find(std::begin(v), std::end(v), i) != std::end(v)) {
++i;
}
return i;
Пришел в надежде на элегантное решение STL, которое использует только одну или две линии. Но, похоже, этого не существует - sad :-) – dhaumann
@dhaumann Да, я думаю, что здесь самая простая вещь, и я все еще чувствовал, что ее нужно перевернуть в функцию. Если ваш вектор можно сортировать, вы можете определенно упростить. Если вы зададите вопрос о сортированном векторе и связываете его здесь, я приду, предоставит 2-строчное решение STL. –
@dhaumann Фактически отмените это, вы можете просто отсортировать, а затем посмотреть на принятый ответ здесь: http://stackoverflow.com/q/27861373/2642059 –