Почему алгоритм O(n^2) работает быстрее, чем алгоритм O(n) на том же входе?

два алгоритма говорят, что A и B написаны для решения одной и той же проблемы. Алгоритм A равен O (n). Алгоритм B равен (N^2). Вы ожидаете, что алгоритм A будет работать лучше.

однако, когда вы запускаете конкретный пример той же машины, алгоритм B работает быстрее. Объясните, как такое могло произойти?

5 ответов


алгоритм A, например, может работать во времени 10000000*n что это O(n).
Если алгоритм B, выполняется в n*n что это O(n^2), A будет медленнее для каждого n < 10000000.

O(n), O(n^2) являются асимптотическими временами выполнения, которые описывают поведение, когда n->infinity

EDIT-EXAMPLE

Предположим, у вас есть две следующие функции:

boolean flag;

void algoA(int n) {
  for (int i = 0; i < n; i++)
    for (int j = 0; j < 1000000; j++)
      flag = !flag;

void algoB(int n) {
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      flag = !flag;

algoA и n*1000000 флаг флип операции, так что это O(n) тогда как algoB и n^2 флаг флип операции, так что это O(n^2).

просто решить неравенство 1000000n > n^2 и вы получите, что для n < 1000000 держит. То есть O(n) метод будет медленнее.


знание алгоритмов поможет дать более точный ответ.

но для общего случая я мог бы подумать о нескольких релевантных факторах:

  • оборудования

    например, если более медленный алгоритм хорошо использует кэширование и локальность или аналогичные низкоуровневые механизмы (см. Производительность Quicksort по сравнению с другими теоретически более быстрыми алгоритмами сортировки). Стоит прочитать о timsort также, как пример где "эффективный" алгоритм используется для разбиения задачи на меньшие входные наборы, а" более простой "и теоретически" более сложный " algo используется на этих наборах, потому что он быстрее.

  • свойства входного набора

    например, если размер входного сигнала мал, эффективность не будет проходить в тесте; также, например, при сортировке снова, если вход в основном предварительно отсортирован против полностью случайного, вы увидите разные результаты. Много различных входных сигналов должны использовать в испытании этого типа для точного результата. Использование только одного примера просто недостаточно, так как вход может быть спроектирован в пользу одного алгоритма вместо другого.

  • конкретная реализация любого алгоритма

    например, есть долгий путь от теоретического описания алгоритма до реализации; плохое использование структур данных, рекурсии,управления памятью и т. д. может серьезно повлиять на производительность


Big-O-notation ничего не говорит о самой скорости, только о том, как скорость изменится, когда вы измените n.

если оба алгоритма занимают одно и то же время для одной итерации, пример @Itay также верен.


в то время как все ответы до сих пор кажутся правильными... ни один из них не чувствует себя действительно "правильным" в контексте класса CS. В курсе вычислительной сложности вы хотите быть точным и использовать определения. Я обрисую много нюансов этого вопроса и вычислительной сложности в целом. К концу мы придем к выводу, почему решение Itay наверху, вероятно, то, что вы должны были написать. Моя главная проблема с решением Itay заключается в том, что ему не хватает определений, которые являются ключом к написанию хорошего доказательства для класса CS. Обратите внимание, что мои определения могут немного отличаться от вашего класса, поэтому не стесняйтесь заменять все, что хотите.

когда мы говорим "алгоритм O(n) " мы на самом деле имеем в виду "этот алгоритм находится в наборе O(n)". И набор O(n) содержит все алгоритмы которого в худшем случае асимптотической сложности f(n) обладает свойством f(n) <= c*n + c_0 для некоторой постоянной c и c_0 здесь c, c_0 > 0.

теперь мы хотим доказать свои претензии. Прежде всего,как вы сформулировали проблему, оно имеет тривиальное решение. Это потому, что наши асимптотические оценки являются "наихудшими". Для многих" медленных " алгоритмов существует какой-то ввод, что он работает удивительно быстро. Например, сортировка вставки является линейной, если вход уже отсортирован! Поэтому возьмите сортировку вставки (O(n)) и сортировка слиянием (O(nlog(n))) и обратите внимание, что сортировка вставки будет работать быстрее, если вы передадите отсортированный массив! Бум, доказательство сделано.

но Я предполагаю, что ваш экзамен означал что-то вроде "покажите, почему линейный алгоритм может работать быстрее, чем квадратичный алгоритм в худшем случае."Как отметил Алекс выше,это открытый вопрос. Суть проблемы заключается в том, что анализ времени выполнения делает предположения, что определенные операции O(1) (например, для некоторой проблемы вы можете предположить, что умножение O(1) даже если он будет квадратично медленнее для больших чисел (можно утверждать, что числа для данная задача ограничена 100-битами, поэтому она по-прежнему"постоянное время")). Поскольку ваш класс, вероятно, фокусируется конкретно на вычислительной сложности, они, вероятно, хотят, чтобы вы замяли эту проблему. Поэтому мы докажем утверждение, предполагая, что наш O(1) предположения верны, и поэтому нет таких деталей, как "кэширование делает этот алгоритм быстрее, чем другой".

Итак, теперь у нас есть один алгоритм, который работает в f(n) что это O(n) и некоторые другие алгоритмы, которые работает в g(n) что это O(n^2). Мы хотим использовать определения, чтобы показать, что для некоторых n можете у нас g(n) < f(n). Фокус в том, что наши предположения не зафиксировали c, c_0, c', c_0'. Как упоминает Итай, мы можем выбрать значения для этих констант, такие, что g(n) < f(n) много n. А остальное доказательство - это то, что он написал выше (например, let c, c_0 быть константами для f(n) и сказать, что они оба 100 в то время как c', c_0' константы для g(n) и они оба 1. Затем g(n) < f(n) => n + 1 < 100n^2 + 100 => 100n^2 - n + 99 > 0 => (factor to get actual bounds for n))


Это зависит от разных сценария.Существует 3 типа сценария 1.Лучше, 2.Средняя, 3.Наихудший. Если вы знаете методы сортировки, происходит то же самое. Для получения дополнительной информации см. следующую ссылку:

http://en.wikipedia.org/wiki/Sorting_algorithm

пожалуйста, поправьте меня, если я ошибаюсь.