O (n log n) vs O (n) - практические различия во временной сложности
n log n > n
- но это похоже на pseudo-linear
зависимость. Если n=1 billion
, log n ~ 30;
Таким образом, n log n
будет 30 billion
, что составляет 30 X n
, порядок n
. Мне интересно, насколько сложна разница в времени между n log n and n
в реальной жизни.
Например: quick select
при поиске k-го элемента в несортированном массиве - O(n)
с использованием алгоритма quickselect.
Если я отсортирую массив и найду k-й элемент, это O(n log n)
. Чтобы отсортировать массив с 1 trillion
элементов, я буду в 60 times
медленнее, если я сделаю quicksort
и index it
.
Ответы
Ответ 1
Основная цель нотации Big-O - позволить вам делать оценки, подобные тем, которые вы делали в своем посте, и решить для себя, если потратить свое усилие на кодирование типично более сложного алгоритма, стоит дополнительных циклов процессора, которые вы будут покупать с этим улучшением кода. В зависимости от обстоятельств вы можете получить другой ответ, даже если ваш набор данных относительно невелик:
- Если вы работаете на мобильном устройстве, и алгоритм представляет значительную часть времени выполнения, сокращение использования процессора приводит к увеличению времени автономной работы.
- Если вы работаете в конкурентной среде "все или ничего", такой как высокочастотная торговая система, микро-оптимизация может различать между зарабатыванием денег и потерей денег.
- Когда ваше профилирование показывает, что рассматриваемый алгоритм доминирует над временем выполнения в серверной среде, переход на более быстрый алгоритм может повысить производительность для всех ваших клиентов.
Другая вещь, которую скрывает нота Big-O, - это постоянный коэффициент умножения. Например, Quick Select имеет очень разумный множитель, что позволяет сэкономить время, используя его на чрезвычайно больших наборах данных, которые стоят проблемы с его реализацией.
Еще одна вещь, которую вам нужно иметь в виду - это сложность пространства. Очень часто алгоритмы с временной сложностью O(N*Log N)
имеют сложность пространства O(Log N)
. Это может представлять проблему для чрезвычайно больших наборов данных, например, когда рекурсивная функция работает в системе с ограниченной емкостью стека.
Ответ 2
Это зависит.
Я работал на amazon, был метод, который выполнял линейный поиск в списке. Мы могли бы использовать Hashtable и искать в O (1) по сравнению с O (n).
Я предложил изменение, и оно не было одобрено. потому что вход был небольшим, на самом деле это не имело бы большого значения.
Однако, если вход большой, тогда это будет иметь значение.
В другой компании, где данные/входные данные были огромными, использование дерева по сравнению с списком имело огромное значение. Это зависит от данных и архитектуры приложения.
Всегда хорошо знать ваши варианты и как вы можете оптимизировать.
Ответ 3
Бывают случаи, когда вы будете работать с миллиардами элементов (и более), где это различие, безусловно, будет значительным.
Есть и другие случаи, когда вы будете работать с менее чем тысячей элементов, и в этом случае разница, вероятно, не будет такой значительной.
Если у вас есть приличное представление о том, как будут выглядеть ваши данные, вы должны иметь приличную идею, которую нужно выбрать с самого начала, но разница между O (n) и O (n log n) достаточно мала, чтобы вероятно, лучше всего начать с того, что проще всего, сравните его и попытайтесь улучшить его, если увидите слишком медленное.
Однако обратите внимание, что O (n) может быть на самом деле медленнее, чем O (n log n) для любого заданного значения n (особенно, но не обязательно, при малых значениях n) из-за постоянных факторов, -O игнорирует их (он учитывает только то, что происходит, когда n стремится к бесконечности), поэтому, если вы смотрите исключительно на сложность времени, то, по вашему мнению, может быть улучшением, может фактически замедлить работу.
Ответ 4
Дарт Вейдер прав. Это всегда зависит. Важно также помнить, что сложности являются асимптотическими, наихудшими (обычно) и что константы отбрасываются. Каждое из них важно рассмотреть.
Таким образом, у вас могут быть два алгоритма, один из которых - O (n), а один из них - O (nlogn), а для каждого значения - до количества атомов во Вселенной и за ее пределами (до некоторого конечного значения n), алгоритм O (nlogn) превосходит алгоритм O (n). Это может быть потому, что доминируют члены более низкого порядка, или это может быть из-за того, что в среднем случае алгоритм O (nlogn) является фактически O (n) или потому, что фактическое количество шагов составляет примерно 5 000 000 n против 3nlogn.
Ответ 5
PriorityQueue Сортирует каждый элемент, который вы добавляете каждый раз при использовании Collections.sort(), сортирует все элементы за один раз. Но если у вас есть проблема, когда вы хотите как можно скорее получить самый большой элемент, используйте PriorityQueue, если вам нужно выполнить некоторые вычисления, но требует сортировки элемента, а затем использовать ArrayList с коллекциями. Сорт лучше