Nano Hash - криптовалюты, майнинг, программирование

почему построение набора из вектора - это O (N)

Поскольку мы знаем, что набор реализован с использованием красно-черных деревьев, поэтому вставка элемента будет задачей сложности O (log N). Но если нам дан вектор из n различных целых чисел, поэтому создание набора из него должно выполняться задачей NlogN. Но во многих местах я обнаружил, что это дается как O (N). Может кто-нибудь, пожалуйста, помогите мне решить эту проблему. Заранее спасибо.

Ссылка на место, где я прочитал это Сложность построения набора из списка?


  • Как вы думаете, почему это O(n)? Построение множества из вектора — это O(n*log n). 27.07.2020
  • @fdan вот в чем вопрос, почему кто-то утверждает, что это O (n), когда не очевидно, почему это так? Ссылка на одно из этих мест не помешала бы. 27.07.2020
  • Вы должны быть более конкретными в отношении каждого конкретного примера, который, по вашему мнению, вы описываете. Возможно, ваш случай не соответствует условиям, изложенным в этом вопросе, или это может быть наилучший сценарий (сортировка уже отсортированного массива), и в этом случае это не имеет значения. 27.07.2020
  • Куча (приоритетная очередь) требует O(N) времени для сборки, если у вас есть все N элементы, которые легко доступны. Сет берет O(NlogN) несмотря ни на что. 27.07.2020
  • But in many places, I found it is given as O(N) Мы не можем рассказать вам о ситуациях, о которых мы не знаем. Пожалуйста, назовите (ссылку) эти многочисленные места (или хотя бы первое). Может быть, есть больше ограничений на ввод, который вы замалчиваете? 27.07.2020
  • Претензия неверна. Если бы мы могли построить набор из несортированного вектора в O(N), мы бы получили алгоритм сортировки O(N). 27.07.2020
  • Как мы знаем... мое понимание скорее обратное: вставка элемента в set определяется как операция O(log N), и красно-черное дерево может достичь этого. 27.07.2020
  • Вставка элементов в кучу также занимает O(logN), но создание кучи из массива может быть выполнено за O(n), хотя математическое доказательство немного длинное. Теория, лежащая в основе этого, заключается в том, что общее количество операций, которые необходимо выполнить, равно n * sum( i / 2^i ) from i = 1 ... logN, что меньше 2n и, следовательно, ограничено O(n). 27.07.2020
  • Но во многих местах дайте ссылки на одно или несколько таких мест. 27.07.2020
  • @n.'местоимения'm. Пожалуйста, найдите ссылку после редактирования. 28.07.2020
  • В этом месте речь идет о хеш-таблицах, а не о деревьях. Один вниз, сколько идти? 28.07.2020
  • так можно ли установить set с помощью хеш-таблицы? 28.07.2020
  • да, это можно реализовать с помощью хеш-таблицы. 28.07.2020

Ответы:


1

Если вектор уже отсортирован, то построение set действительно O(N) (но в общем случае нет!).

Из cppreference:

template< class InputIt >    
set( InputIt first, InputIt last,
     const Compare& comp = Compare(),
     const Allocator& alloc = Allocator() );

Конструктор диапазона. Создает контейнер с содержимым диапазона [first, last). Если несколько элементов в диапазоне имеют ключи, которые сравниваются эквивалентными, не указано, какой элемент вставляется.

Сложность

N log(N), где N = std::distance(first, last) в общем случае линейно по N, если диапазон уже отсортирован с помощью value_comp().

Соответствующая цитата из стандарта:

22.4.6.2#4 Сложность: линейна по N, если диапазон [first ,последний) уже отсортирован с помощью comp и иначе NlogN, где N последний - первый.

Стандарт определяет только то, что контейнеры делают, а не то, как они это делают. Использование красно-черного дерева типично, но не обязательно для реализации std::set.

27.07.2020
  • Как это линейно? Может ли кто-нибудь связать меня с объяснением, я не нашел ничего, связанного с этим. 27.07.2020
  • @ srt1104 Я не мог обосновать это математикой, но, по сути, операция является линейной с отсортированным вектором, потому что вы можете использовать позицию, в которой был вставлен предыдущий элемент, в качестве подсказки, чтобы вставить следующий элемент быстрее. 27.07.2020
  • Тем не менее, дереву придется когда-нибудь переупорядочиваться, и это операция logN. 27.07.2020
  • @ srt1104 Более умные люди, чем я, сказали, что это O (N), включая любую перебалансировку, на самом деле стандарт C ++ гарантирует это. 27.07.2020
  • Обратите внимание, что для построения нового набора требуется только O (N), вставка в существующий набор по-прежнему O (N log (N)) 27.07.2020
  • @ srt1104 нет, вы помещаете значения прямо туда, где они должны заканчиваться. Только если вы обнаружите, что ввод неупорядочен, вам нужно изменить порядок того, что вы уже добавили. 28.07.2020
  • @john добавление отсортированной последовательности к существующему набору также является O (N) в существующих реализациях, потому что они просто повторно используют тот же алгоритм, что и для построения из отсортированной последовательности (неоднократно вызывая подсказанный set::insert с end() в качестве подсказки) 31.07.2020
  • @Cubbi Я знаю это, но я помню, что читал, что это не O (N). Суть того, что я прочитал, заключалась в том, что изначально предполагалось, что это O (N), но затем кто-то, лучше разбирающийся в мемтемтике, указал, что это не так, и стандарт пришлось пересмотреть. Но мои воспоминания могут быть ошибочными, это было давно. Если у кого-то есть доступ к стандарту сейчас, мне было бы интересно узнать. 31.07.2020
  • @Cubbi Итак, cppreference говорит об этом Amortized constant if the insertion happens in the position just before the hint, logarithmic in the size of the container otherwise. Я думаю, дело в том, что если карта уже содержит элементы, то вы не можете гарантировать, что вставка произойдет в позиции непосредственно перед подсказкой. Таким образом, одна вставка — это O(logN), а предположительно N вставок — это O(NlogN). 31.07.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..