Как найти ближайшее меньшее число в массиве?

Рассмотрим этот массив:

std::vector<int> numbers = { 0, 4, 12, 60, 89 };

Он отсортирован и имеет только положительные числа.

Как проще всего найти ближайшее меньшее число в массиве, желательно от <algorithm>? Пример:

Число Результат 0 0 3 0 15 12 74 60 150 89

Поскольку вы описываете отсортированный массив (который, предположительно, при тестировании будет намного больше), какой-то двоичный поиск, вероятно, будет «самым простым» способом достижения этой цели, где самым простым является «наименьшая временная сложность». Не уверен, что что-либо в <algorithm> покрывает это.

Chris 09.04.2024 20:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
165
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как проще всего найти ближайшее меньшее число в массиве, желательно от <algorithm>?

Для этого можно использовать уже существующий std::lower_bound (или std::ranges::lower_bound, начиная с C++20). Проверьте пример кода, приведенный на указанных страницах.

Например, вы можете написать функцию следующим образом. Я оставляю вам обработку ошибок, а также доработку крайних случаев.

#include <algorithm>  // std::ranges::lower_bound

constexpr auto find_equal_or_closest(std::vector<int> const& numbers, const int query)
{
    // invalid query/ not able to find cases!
    // you could also restructure to return std::cend(numbers) from function.
    if (numbers.empty() 
        /* || !std::ranges::is_sorted(numbers) */ // optional check
        || query < *std::cbegin(numbers)
        )       
        return -1; 

    auto it = std::ranges::lower_bound(numbers, query);
    return (it != std::cend(numbers) && *it == query) ? *it : *std::prev(it);
}

Посмотрите живую демонстрацию

Нижняя граница возвращает первую, которая не меньше заданного значения.

n. m. could be an AI 09.04.2024 20:42

Скорректировано на основе вашего обновленного ответа... Мне нравится этот трюк... все еще используйте low_bound, но потом настройте итератор....

UpAndAdam 09.04.2024 20:53

отказываюсь от своего закрытого голосования, потому что это намного лучше, чем другой ответ, ИМХО

UpAndAdam 09.04.2024 20:57

@UpAndAdam Как уже упоминалось, это не идеальное решение, а скорее направление к реальной проблеме ОП. ОП должен думать/обрабатывать все потоки в данном случае в соответствии со своими крайними случаями.

JeJo 09.04.2024 21:04

Извините, забыл удалить свой первый ответ. Должен сказать, что мне это нравится, это так просто, но я никогда раньше об этом не думал. Для меня это теперь идеальное решение. И бонусные баллы за живую демонстрацию с Godbolt... Мне нужно начать делать это в своих ответах. Вы действительно отличный пользователь с высокой репутацией, я отдаю вам должное. В последнее время у меня было так много неприятных событий с людьми с высокой репутацией, что это действительно освежает. Образцовое движение туда-сюда. Спасибо, что показали мне, как лучше самому отвечать на вопросы.

UpAndAdam 09.04.2024 21:05

когда в массиве нет меньшего числа, вы возвращаете итератор первому элементу, в этом случае я бы предпочел ожидать end

463035818_is_not_an_ai 09.04.2024 21:47

ооо, это хороший угловой случай. @463035818_is_not_an_ai не подумал об этом... забавные угловые случаи.

UpAndAdam 09.04.2024 21:59

Другие вопросы по теме

Пользовательский раскрывающийся список с (переключателями и флажками) в реакции. возможный?
Как сделать переменные одинаковыми для всех структур в массиве структур
Создать массив на основе вложенного массива
Цикл for OCaml, похоже, выполняет больше, чем ожидалось
Пропустил шаг? Использование массивов (обязательных) для преобразования шестнадцатеричной строки в десятичную (Int)
Элемент TS 7023 неявно имеет тип «любой», поскольку выражение типа «любой» не может использоваться для индексации типа «{}»
Как избежать «RuntimeWarning: деление на ноль, обнаруженное в log10» в цикле for с более чем 20 000 элементов?
Эффективный способ вернуть один элемент по приоритету в массиве объектов javascript
Группировка Json с одинаковым значением ключа с помощью Jolt
Как превратить динамически распределенный массив C в массив Numpy и вернуть его в Python в модуле расширения C