Что такое простое английское объяснение обозначения "Big O"?

Я бы предпочел как можно меньше формального определения и простую математику.

30 ответов


быстрое Примечание, это почти наверняка заблуждение Big O notation (который является верхней границей) с тета-нотацией (которая является двусторонней границей). По моему опыту, это на самом деле типично для дискуссий в неакадемических условиях. Прошу прощения за возникшую путаницу.


сложность Big O можно визуализировать с помощью этого графика:

Big O Analysis

самое простое определение, которое я могу дать для обозначения Big-O, это:

Big-O нотация-это относительное представление сложности алгоритма.

в этом предложении есть несколько важных и намеренно выбранных слов:

  • родственник: вы можете только сравнивать яблоки с яблоками. Вы не можете сравнить алгоритм арифметического умножения с алгоритмом, который сортирует список целых чисел. Но сравнение двух алгоритмов для выполнения арифметических операций (одно умножение, одно сложение) будет сказать вам что-нибудь значимое;
  • представление: Big-O (в его простейшей форме) уменьшает сравнение между алгоритмами до одной переменной. Эта переменная выбирается на основе наблюдений или предположений. Например, алгоритмы сортировки обычно сравниваются на основе операций сравнения (сравнение двух узлов для определения их относительного порядка). Это предполагает, что сравнение дорого. Но что, если сравнение дешево, а обмен дорог? Он изменяет сравнение; и
  • сложность: если мне потребуется одна секунда, чтобы отсортировать 10 000 элементов, сколько времени мне потребуется, чтобы отсортировать миллион? Сложность в данном случае является относительной мерой к чему-то другому.

вернитесь и перечитайте выше, если вы читали остальные.

лучший пример Big-O, который я могу придумать, - это арифметика. Возьмем два числа (123456 и 789012). Основные арифметические операции мы учились в школе были:

  • дополнительно;
  • вычитание;
  • умножение; и
  • дивизии.

каждый из них является операция или проблемы. Метод их решения называется алгоритм.

дополнение является самым простым. Вы выстраиваете числа вверх (вправо) и добавляете цифры в столбец, записывая последнее число этого добавления в результате. Часть "десятки" этого числа переносится в следующий столбец.

предположим, что сложение этих чисел является самой дорогой операцией в этом алгоритме. Само собой разумеется, что для сложения этих двух чисел мы должны сложить вместе 6 цифр (и, возможно, нести 7-й). Если мы сложим два 100-значных числа вместе, мы должны сделать 100 дополнений. Если добавить два 10 000 цифр мы должны сделать 10 000 дополнений.

посмотреть шаблон? The сложности (количество операций) прямо пропорционально количеству цифр n в большем количестве. Мы называем это O (n) или линейной сложности.

вычитание похож (кроме вас нужна, а не нести).

умножение другая. Вы выстраиваете числа в линию, берете первую цифру в Нижнем числе и умножаете ее по очереди против каждой цифры в верхнем числе и так далее через каждую цифру. Итак, чтобы умножить наши два 6-значных числа, мы должны сделать 36 умножений. Возможно, нам придется добавить 10 или 11 столбцов, чтобы получить конечный результат.

Если у нас есть два 100-значных числа, нам нужно сделать 10 000 умножения и 200 добавляет. Для двух миллионов цифр нам нужно сделать один триллион (1012) умножений и два миллиона добавляет.

как алгоритм масштабируется с n -квадрат, это O (n2) или квадратичную сложность. Это хорошее время, чтобы ввести еще одну важную концепцию:

мы заботимся только о самой значительной части сложности.

проницательный, возможно, понял, что мы могли бы выразить количество операций как: N2 + 2n. Но как вы видели из нашего примера с двумя числами по миллиону цифр за штуку, второй член (2n) становится несущественным (на этот этап приходится 0,0002% от общего объема операций).

можно заметить, что мы предположили худший сценарий здесь. При умножении 6-значных чисел, если одно из них 4-значное, а другое 6-значное, то у нас есть только 24 умножения. Тем не менее, мы вычисляем худший сценарий для этого "n", i.e когда оба являются 6-значными числами. Следовательно, обозначение Big-O - это наихудший сценарий алгоритма

Телефонная Книга

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

типичной реализацией может быть Открытие до середины, возьмите 500,000th и сравните его с "Smith". Если это окажется "Смит, Джон", нам просто очень повезло. Гораздо более вероятно, что "Джон Смит" будет до или после этого имя. Если это после того, как мы разделим последнюю половину телефонной книги пополам и повторим. Если это до того, то мы делим первую половину телефонной книги пополам и повторяем. И так далее.

Это называется бинарный поиск и используется каждый день в программировании, понимаете вы это или нет.

Итак, если вы хотите найти имя в телефонной книге миллиона имен, вы можете найти любое имя, сделав это не более 20 раз. При сравнении алгоритмов поиска мы решаем, что это сравнение является нашим "n".

  • для телефонной книги из 3 имен требуется 2 сравнения (не более).
  • для 7 это занимает не более 3.
  • за 15 за 4.
  • ...
  • для 1,000,000 оно принимает 20.

Это потрясающе хорошо, не так ли?

в терминах Big-O это O (log n) или логарифмическую сложность. Теперь логарифм, о котором идет речь, может быть ln (база e), log10, log2 или какая-то другая база. Это не имеет значения, это все еще O (log n) так же, как O (2n2) и O (100n2) по-прежнему оба O (n2).

на данный момент стоит объяснить, что Big O можно использовать для определения трех случаев с помощью алгоритма:

  • Лучший Вариант: в телефонной книге поиска, в лучшем случае, что мы находим имя в одном сравнении. Это O (1) или постоянные сложности;
  • ожидается Дело: как обсуждалось выше, это O (log n); и
  • В Худшем Случае: это также O (log n).

обычно мы не заботимся о лучшем случае. Нас интересует ожидаемый и наихудший случай. Иногда одно из них будет более важным.

назад к телефонной книге.

Что делать, если у вас есть номер телефона и вы хотите, чтобы найти имя? У полиции есть обратная телефонная книга, но такая широкой публике отказано в поиске. Или нет? Технически вы можете перевернуть поиск номера в обычной телефонной книге. Как?

вы начинаете с первого имени и сравниваете номер. Если совпадение, отлично, если нет, переходите к следующему. Вы должны сделать это таким образом, потому что телефонная книга ненумерованный (по номеру телефона в любом случае).

найти название по номеру телефона (обратный поиск):

  • Лучший Вариант: O (1);
  • Ожидается Делу: O (n) (для 500,000); и
  • В Худшем Случае: O (n) (для 1,000,000).

Коммивояжер

Это довольно известная проблема в информатике и заслуживает упоминания. В этой задаче у вас есть N городов. Каждый из этих городов связан с 1 или более другими городами дорогой на определенное расстояние. Этот Задача коммивояжера найти самый короткий тур, который посещает каждый город.

звучит просто? Снова подумать.

Если у вас есть 3 города A, B и C с дорогами между всеми парами, то вы можете пойти:

  • A → B → C
  • A → C → B
  • B → C → A
  • B → A → C
  • C → A → B
  • C → B → A

ну на самом деле там меньше потому что некоторые из них эквивалентны (A → B → C и C → B → A эквивалентны, например, потому что они используют одни и те же дороги, только наоборот).

на самом деле есть 3 возможности.

  • возьмите это в 4 города, и у вас есть (iirc) 12 возможностей.
  • С 5 это 60.
  • 6 становится 360.

Это функция математической операции, называемой факторный. В основном:

  • 5! = 5 × 4 × 3 × 2 × 1 = 120
  • 6! = 6 × 5 × 4 × 3 × 2 × 1 = 720
  • 7! = 7 × 6 × 5 × 4 × 3 × 2 × 1 = 5040
  • ...
  • 25! = 25 × 24 × ... × 2 × 1 = 15,511,210,043,330,985,984,000,000
  • ...
  • 50! = 50 × 49 × ... × 2 × 1 = 3.04140932 × 1064

таким образом, Big-O проблемы коммивояжера O (n!) или факториальная или комбинаторная сложность.

к тому времени, когда вы доберетесь до 200 городов, во Вселенной не хватит времени, чтобы решить проблему с традиционными компьютерами.

есть о чем подумать.

Полиномиальное Время

еще один момент, о котором я хотел бы быстро упомянуть, заключается в том, что любой алгоритм имеет сложность O (na) говорят, полиномиальной сложности или разрешима в полиномиальное время.

O(n), O (N2) и т. д. Все полиномиальное время. Некоторые проблемы не могут быть решены за полиномиальное время. Некоторые вещи используются в мире из-за этого. Ярким примером является криптография с открытым ключом. Вычислительно трудно найти два простых фактора очень большого числа. Если бы это было не так, мы не могли бы использовать системы открытых ключей, которые мы используем.

в любом случае, это мое (надеюсь, простое английское) объяснение Big O (пересмотрено).


он показывает, как масштабируется алгоритм.

O (n2): как квадратичную сложность

  • 1 пункт: 1 секунда
  • 10 предметов: 100 секунд
  • 100 деталей: 10000 секунд

обратите внимание, что количество элементов увеличивается в 10 раз, но время увеличивается в 10 раз2. В принципе, n=10 и так O (n2) дает нам коэффициент масштабирования n2 что 102.

O (n): как линейной сложности

  • 1 пункт: 1 секунда
  • 10 пунктов: 10 секунд
  • 100 пунктов: 100 секунд

на этот раз количество элементов увеличивается в 10 раз, а также время. n=10, поэтому коэффициент масштабирования O(n) равен 10.

O (1): как постоянная сложность

  • 1 пункт: 1 секунда
  • 10 пунктов: 1 секунду
  • 100 пунктов: 1 секунда

количество элементов по-прежнему увеличивается в 10 раз, но коэффициент масштабирования O(1) всегда равен 1.

O (log n): как логарифмическую сложность

  • 1 пункт: 1 секунда
  • 10 предметов: 2 секунды
  • 100 деталей: 3 секунды!--14-->
  • 1000 предметов: 4 секунды
  • 10000 деталей: 5 секунд

количество вычислений увеличивается только на лог входного значения. Таким образом, в этом случае, предполагая, что каждое вычисление занимает 1 секунду, журнал ввода n требуется время, следовательно log n.

в этом суть. Они уменьшают математику вниз, так что это может быть не совсем n2 или, как они говорят, но это будет доминирующим фактором в масштабирование.


обозначение Big-O (также называемое обозначением "асимптотического роста") -какие функции "выглядят" , когда вы игнорируете постоянные факторы и вещи рядом с началом. Мы используем его, чтобы говорить о как масштаб вещи.


основы

для "достаточно" больших входных сигналов...

  • f(x) ∈ O(upperbound) означает f "растет не быстрее, чем" upperbound
  • f(x) ∈ Ɵ(justlikethis) mean f "растет точно так же, как"justlikethis
  • f(x) ∈ Ω(lowerbound) означает f "растет не медленнее, чем" lowerbound

обозначение big-O не заботится о постоянных факторах: функция 9x² говорят, что "растут точно так же, как"10x². Как и Биг-о асимптотические обозначения заботятся о не-асимптотические материал ("материал рядом с источником" или " что происходит, когда размер проблемы небольшой"): функция 10x² говорят, что "растут точно так же, как"10x² - x + 2.

почему вы хотите игнорировать меньшие части уравнения? Потому что они становятся совершенно карликовыми по сравнению с большими частями уравнения, когда вы рассматриваете все большие и большие масштабы; их вклад становится карликовым и неуместным. (См. примерный раздел.)

другими словами, это все о соотношение как вы идете до бесконечности. если вы делите фактическое время его принимает O(...), вы получите постоянный коэффициент в пределе больших входов. интуитивно это имеет смысл: функции "масштабируются как" друг друга, если вы можете умножить один, чтобы получить другой. То есть, когда мы говорим...

actualAlgorithmTime(N) ∈ O(bound(N))
                                       e.g. "time to mergesort N elements 
                                             is O(N log(N))"

... это значит, что для" достаточно больших " размеров задачи n (если мы игнорируем материал вблизи начала координат), существует некоторая константа (например, 2.5, полностью составленная) такая, что:

actualAlgorithmTime(N)                 e.g. "mergesort_duration(N)       "
────────────────────── < constant            ───────────────────── < 2.5 
       bound(N)                                    N log(N)         

там есть много вариантов константы; часто "лучший" выбор известен как" постоянный фактор " алгоритма... но мы часто игнорируем его, как игнорируем не самые большие термины (см. раздел "постоянные факторы", почему они обычно не имеют значения). Вы также можете думать о приведенном выше уравнении как о границе, говоря:"в худшем случае, время никогда не будет хуже, чем ориентировочно N*log(N), в пределах коэффициента 2,5 (постоянный фактор, о котором мы не заботимся)".

In общие O(...) является наиболее полезным, потому что мы часто заботимся о худшем случае. Если f(x) представляет собой что-то "плохое", как процессор или память, то "f(x) ∈ O(upperbound)" значит "upperbound является наихудшим сценарием использования процессора / памяти".


приложения

как чисто математическая конструкция, нотация big-O не ограничивается разговорами о времени обработки и памяти. Вы можете использовать его для обсуждения асимптотики все, где масштабирование имеет смысл, например:

  • количество возможных рукопожатий среди N люди на вечеринке (Ɵ(N²), в частности N(N-1)/2, но важно то, что он "весы вроде" )
  • вероятностное ожидаемое количество людей, которые видели некоторый вирусный маркетинг в зависимости от времени
  • как задержка веб-сайта масштабируется с количеством процессоров в CPU или GPU или компьютерном кластере
  • как масштабы выхода жары на плашках К. П. У. Как функция отсчета транзистора, напряжения тока, ЕТК.
  • сколько времени должен работать алгоритм, в зависимости от размера ввода
  • сколько места должен работать алгоритм, в зависимости от размера ввода

пример

для примера рукопожатия выше, каждый в комнате пожимает руку всем остальным. В этом примере #handshakes ∈ Ɵ(N²). Почему?

резервное копирование a бит: количество рукопожатий ровно n-choose-2 или N*(N-1)/2 (каждый из N людей пожимает руки N-1 другим людям, но это двойное количество рукопожатий, поэтому разделите на 2):

everyone handshakes everyone else. Image credit and license per wikipedia/wikimedia commons "complete graph" article. adjacency matrix

однако для очень большого числа людей линейный термин N является карликовым и эффективно вносит 0 в соотношение (на диаграмме: доля пустых ящиков по диагонали над общими ящиками становится меньше, поскольку количество участников становится больше). Поэтому поведение масштабирования order N², или количество рукопожатий "растет как N2".

#handshakes(N)
────────────── ≈ 1/2
     N²

как будто пустых ящиков на диагонали графика (N * (N-1)/2 галочки) даже не было (N2 галочки асимптотически).

(временное отступление от "простого английского":) Если вы хотите доказать это себе, вы можете выполнить простую алгебру по отношению, чтобы разделить ее на несколько условия (lim означает "рассматривается в пределе", просто игнорируйте его, если вы его не видели, это просто обозначение для "и N действительно очень большой"):

    N²/2 - N/2         (N²)/2   N/2         1/2
lim ────────── = lim ( ────── - ─── ) = lim ─── = 1/2
N→∞     N²       N→∞     N²     N²      N→∞  1
                               ┕━━━┙
             this is 0 in the limit of N→∞:
             graph it, or plug in a really large number for N

tl; dr: количество рукопожатий "выглядит как" x2 так много для больших значений, что если бы мы должны были записать соотношение #рукопожатия/x2, тот факт, что нам не нужно ровно рукопожатия x2 даже не будут отображаться в десятичной дроби в течение произвольно большого времени.

например, для x=1million, соотношение #рукопожатия / x2: 0.499999...


Строительство Интуицию

это позволяет нам делать такие заявления...

" для достаточно большого inputsize=N, независимо от того, какой постоянный коэффициент, если I двойной размер входных данных...

  • ... Я удваиваю время, которое занимает алгоритм O(N) ("линейное время")."

    N → (2N) = 2(N)

  • ... I двойной квадрат (квадратичный) время, которое занимает алгоритм O(N2) ("квадратичное время")."(например, проблема 100х как большой берет 1002=10000x как долго... возможно, неустойчивый)

    N2 → (2N) 2 = 4(N2)

  • ... I двойной куб (octuple) время O (N3) ("кубическое время") алгоритм берет."(например, проблема 100х как большой берет 1003=1000000x как долго... очень неустойчиво)

    cn3 для → c (2N)3 = 8 (cn3 для)

  • ... Я добавляю фиксированную сумму к времени, которое занимает алгоритм O(log(N)) ("логарифмическое время")."(дешевые!)

    c log (N) → c log (2N) = (c log (2))+(c log (N)) = (исправлено сумма)+(c log (N))

  • ... Я не изменяю время, которое занимает алгоритм O(1) ("постоянное время")."(самый дешевый!)

    c * 1c * 1

  • ... I "(в основном) удваивает " время, которое занимает алгоритм O(N log(N))."(довольно распространенная)

    это меньше, чем O (N1.000001), которое вы могли бы назвать в основном линейный

  • ... Я смехотворно увеличиваю время A O (2N) ("экспоненциальное время") алгоритм принимает."(вы бы удвоили (или утроили и т. д.) время просто за счет увеличения задачи на единицу)

    2N → 22N = (4N)............положи еще путь...... 2N → 2N+1 = 2N21 = 2 2N

[для математически склонных, вы можете наведите курсор мыши на спойлеры для незначительных Примечаний]

(с кредитом на https://stackoverflow.com/a/487292/711085)

(технически постоянный фактор может иметь значение в некоторых более эзотерические примеры, но я сформулировал вещи выше (например, в log (N)) так, что это не так)

это хлеб с маслом порядки роста, которые программисты и прикладные компьютерные ученые используют в качестве опорных точек. Они видят это все время. (Поэтому, хотя вы могли бы технически подумать ,что "удвоение ввода делает алгоритм O(√N) в 1,414 раза медленнее", лучше думать об этом как "это хуже, чем логарифмическое, но лучше, чем линейный.")


постоянные факторы

обычно нам все равно, каковы конкретные постоянные факторы, потому что они не влияют на то, как растет функция. Например, два алгоритма могут принимать значение O(N) время для завершения, но один может быть в два раза медленнее, чем другой. Мы обычно не заботимся слишком много, если фактор не очень велик, так как оптимизация-это сложный бизнес (когда оптимизация преждевременна? ), а также простой акт выбора алгоритма с лучшим big-O часто улучшает производительность на порядки.

некоторые асимптотически превосходящие алгоритмы (например, несопоставление O(N log(log(N))) сортировка) может иметь такой большой постоянный коэффициент (например,100000*N log(log(N))), или накладные расходы, которые относительно велики, как O(N log(log(N))) со скрытым + 100*N, что они редко стоит использовать даже на "больших данных".


почему O (N) иногда лучшее, что вы можете сделать, т. е. Почему нам нужно структур

O(N) алгоритмы в некотором смысле являются "лучшими" алгоритмами, если вам нужно прочитать все ваши данные. The чтение куча данных O(N) операции. Загрузка его в память обычно O(N) (или быстрее, если у вас есть аппаратная поддержка, или вообще нет времени, если вы уже прочитали данные). Однако, если вы касаетесь или даже посмотреть на каждом фрагменте данных (или даже на каждом другом фрагменте данных) ваш алгоритм возьму O(N) время выполнить этот смотреть. Nomatter сколько времени займет ваш фактический алгоритм, это будет по крайней мере O(N) потому что он потратил это время на просмотр всех данных.

то же самое можно сказать о сам факт написания. Все алгоритмы, которые распечатывают N вещей, займут N времени, потому что выход по крайней мере такой длинный (например, печать всех перестановок (способов перестановки) набор из N игральных карт является факториальным: O(N!)).

это мотивирует использование структуры данных: структура данных требует чтения данных только один раз (обычно O(N) время), плюс некоторое произвольное количество предварительной обработки (например,O(N) или O(N log(N)) или O(N²)), которые мы стараемся сохранить маленький. После этого, изменение структуры данных (вставки / удаления / etc.) и выполнение запросов к данным занимает очень мало времени, например O(1) или O(log(N)). Затем вы продолжаете делать большое количество запросы! В общем, чем больше работы вы готовы сделать раньше времени, тем меньше работы вам придется делать позже.

например, скажем, у вас были координаты широты и долготы миллионов сегментов дорог и вы хотели найти все перекрестки улиц.

  • наивный метод: если бы у вас были координаты перекрестка улиц и вы хотели бы исследовать близлежащие улицы, вам пришлось бы каждый раз проходить через миллионы сегментов и проверять каждый из них смежность.
  • если бы вам нужно было сделать это только один раз, не было бы проблемой сделать наивный метод O(N) работает только один раз, но если вы хотите сделать это много раз (в данном случае N раз, один раз для каждого сегмента), мы должны были бы сделать O(N²) работа, или 10000002=1000000000000 операций. Не очень хорошо (современный компьютер может выполнять около миллиарда операций в секунду).
  • если мы используем простую структуру, называемую хэш-таблицей (таблица мгновенного поиска, также известный как hashmap или словарь), мы платим небольшую стоимость, предварительно обрабатывая все в O(N) времени. После этого требуется только постоянное время в среднем, чтобы найти что-то по его ключу (в этом случае наш ключ-это координаты широты и долготы, округленные в сетку; мы ищем соседние области сетки, из которых есть только 9, что является константой).
  • наша задача вышла из невыполнимой O(N²) до разумных пределов O(N), а всего надо было заплатить небольшую стоимость сделать хэш-таблицу.
  • аналогия: аналогия в этом конкретном случае-головоломка: мы создали структуру данных, которая использует некоторое свойство данных. Если наши сегменты дороги похожи на кусочки головоломки, мы группируем их по цвету и рисунку. Затем мы используем это, чтобы избежать дополнительной работы позже (сравнивая кусочки головоломки подобного цвета друг с другом, а не с каждым другим кусочком головоломки).

мораль истории: данные структура позволяет нам ускорить работу. Еще более продвинутые структуры данных позволяют комбинировать, задерживать или даже игнорировать операции невероятно умными способами. У разных проблем будут разные аналогии, но все они будут включать в себя организацию данных таким образом, чтобы использовать какую-то структуру, о которой мы заботимся, или которую мы искусственно наложили на нее для бухгалтерского учета. Мы работаем раньше времени (в основном планируем и организуем), и теперь повторных задач намного больше легче!


практический пример: визуализация порядков роста при кодировании

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

основы: всякий раз, когда мы взаимодействуем с каждым элементом в коллекции размера (например, массив, комплект, все ключи, карты и т. д.), или выполнить итерации цикла, то есть мультипликативный фактор размера A. почему я говорю "мультипликативный фактор"?-- потому что циклы и функции (почти по определению) имеют мультипликативное время выполнения: количество итераций, время работы в цикле (или для функций: количество раз, когда вы вызываете функцию, время работы в функции). (Это справедливо, если мы не делаем ничего необычного, например, пропустить петли или выйти цикл рано или изменить поток управления в функции на основе аргументов, что очень распространено.) Вот несколько примеров техник визуализации с сопутствующим псевдокодом.

(здесь xs представляют собой постоянные единицы времени работы, инструкции процессора, коды интерпретатора, что угодно)

for(i=0; i<A; i++)        // A x ...
    some O(1) operation     // 1

--> A*1 --> O(A) time

visualization:

|<------ A ------->|
1 2 3 4 5 x x ... x

other languages, multiplying orders of growth:
  javascript, O(A) time and space
    someListOfSizeA.map((x,i) => [x,i])               
  python, O(rows*cols) time and space
    [[r*c for c in range(cols)] for r in range(rows)]

Пример 2:

for every x in listOfSizeA:   // A x ...
    some O(1) operation         // 1
    some O(B) operation         // B
    for every y in listOfSizeC: // C x ...
        some O(1) operation       // 1

--> O(A*(1 + B + C))
    O(A*(B+C))        (1 is dwarfed)

visualization:

|<------ A ------->|
1 x x x x x x ... x

2 x x x x x x ... x ^
3 x x x x x x ... x |
4 x x x x x x ... x |
5 x x x x x x ... x B  <-- A*B
x x x x x x x ... x |
................... |
x x x x x x x ... x v

x x x x x x x ... x ^
x x x x x x x ... x |
x x x x x x x ... x |
x x x x x x x ... x C  <-- A*C
x x x x x x x ... x |
................... |
x x x x x x x ... x v

Пример 3:

function nSquaredFunction(n) {
    total = 0
    for i in 1..n:        // N x
        for j in 1..n:      // N x
            total += i*k      // 1
    return total
}
// O(n^2)

function nCubedFunction(a) {
    for i in 1..n:                // A x
        print(nSquaredFunction(a))  // A^2
}
// O(a^3)

если мы сделаем что-то немного сложное, вы все равно сможете чтобы визуально представить, что происходит:

for x in range(A):
    for y in range(1..x):
        simpleOperation(x*y)

x x x x x x x x x x |
x x x x x x x x x   |
x x x x x x x x     |
x x x x x x x       |
x x x x x x         |
x x x x x           |
x x x x             |
x x x               |
x x                 |
x___________________|

здесь имеет значение наименьший узнаваемый контур, который вы можете нарисовать; треугольник-это двумерная форма (0.5 A^2), так же как квадрат-двумерная форма (A^2); постоянный фактор двух здесь остается в асимптотическом соотношении между ними, однако мы игнорируем его, как и все факторы... (В этой технике есть некоторые неприятные нюансы, в которые я здесь не вдаюсь; она может ввести вас в заблуждение.)

конечно, это это не означает, что циклы и функции плохи; наоборот, они являются строительными блоками современных языков программирования, и мы их любим. Однако мы можем видеть, что способ, которым мы плетем петли, функции и условные обозначения вместе с нашими данными (поток управления и т. д.) имитирует использование времени и пространства нашей программы! Если использование времени и пространства становится проблемой, то есть когда мы прибегаем к уму и находим простой алгоритм или структуру данных, которые мы не рассматривали, чтобы уменьшить порядок роста как-то. Тем не менее, эти методы визуализации (хотя они не всегда работают) могут дать вам наивное предположение в худшем случае.

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

<----------------------------- N ----------------------------->
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x x
x x x x x x x x
x x x x
x x
x

мы можем просто переставить это и увидеть, что это O (N):

<----------------------------- N ----------------------------->
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x x|x x x x x x x x|x x x x|x x|x

или, может быть, вы регистрируете (N) проходы данных, для O(N*log (N)) общее время:

   <----------------------------- N ----------------------------->
 ^  x x x x x x x x x x x x x x x x|x x x x x x x x x x x x x x x x
 |  x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x x x x
lgN x x x x|x x x x|x x x x|x x x x|x x x x|x x x x|x x x x|x x x x
 |  x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x|x x
 v  x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x|x

Несвязанно, но стоит упомянуть еще раз: если мы выполняем хэш (например, a dictionary / Hashtable lookup), то есть коэффициент O(1). Это довольно быстро.

[myDictionary.has(x) for x in listOfSizeA]
 \----- O(1) ------/    

--> A*1 --> O(A)

если мы делаем что-то очень сложное, например, с рекурсивной функцией или алгоритмом разделения и завоевания,можно использовать Главная Теорема (обычно работает), или в смешных случаях Теорема АКРА-Баззи (почти всегда работает) вы смотрите время работы вашего алгоритма в Википедии.

но программисты так не думают, потому что в конце концов, интуиция алгоритма просто становится второй натурой. Вы начнете кодировать что-то неэффективное и сразу подумаете: "Я что-то делаю крайне неэффективно?". Если ответ "да" , и вы предвидите, что это действительно важно, то вы можете сделать шаг назад и подумать о различных трюках, чтобы заставить вещи работать быстрее (ответ почти всегда "использовать хэш-таблицу", редко "использовать дерево" и очень редко что-то немного больше сложный.)


Амортизированная и среднеквадратичная сложность

существует также понятие "амортизированный" и / или "средний случай" (обратите внимание, что они отличаются).

Обычное Дело: это не более чем использование обозначения big-O для ожидаемого значения функции, а не самой функции. В обычном случае, когда вы считаете, все входы должны быть равновероятны, то среднее всего среднее время выполнения. Например, с quicksort, хотя в худшем случае это O(N^2) для некоторых действительно плохих входов средний случай является обычным O(N log(N)) (действительно плохие входы очень малы по количеству, так мало, что мы не замечаем их в среднем случае).

Амортизированный Худший Случай: некоторые структуры данных могут иметь наихудшую сложность, которая велика, но гарантируют, что если вы выполните многие из этих операций, средний объем работы будет лучше, чем наихудший. Например, у вас может быть структура данных, которая обычно принимает константу O(1) времени. Однако иногда он будет "икать" и принимать O(N) время для одной случайной операции, потому что, возможно, ему нужно сделать какую-то бухгалтерию или сбор мусора или что-то еще... но он обещает вам, что если он будет икать, он не будет икать снова для N больше операций. В худшем случае стоимость по-прежнему O(N) за операцию, но амортизированная стоимость на протяжении многих работает is O(N)/N = O(1) за операцию. Поскольку крупные операции достаточно редки, можно считать, что огромное количество случайной работы сливается с остальной работой как постоянный фактор. Мы говорим, что работа "амортизируется" за достаточно большое количество вызовов, что она исчезает асимптотически.

аналогия для амортизированного анализа:

Ты водишь машину. Иногда вам нужно потратить 10 минут на то, чтобы АЗС, а затем потратить 1 минуту заправка бака бензином. Если вы делали это каждый раз, когда вы ездили куда-нибудь на своем автомобиле (потратьте 10 несколько минут езды до заправки, несколько секунд заправки часть галлона), это было бы очень неэффективно. Но если вы заполните бак раз в несколько дней, в 11 минут на машине до АЗС "амортизируется" за достаточно большое количество поездок, что ты можешь игнорировать это и притворяться, что все твои поездки были, может быть, 5% длиннее.

сравнение между средним случаем и амортизированным худшим случаем:

  • средний случай: мы делаем некоторые предположения о наших входах; т. е. если наши входы имеют разные вероятности, то наши выходы / время выполнения будут иметь разные вероятности (которые мы принимаем в среднем). Обычно мы предполагаем, что все наши входы одинаково вероятны( равномерная вероятность), но если реальные входы не соответствуют нашим предположениям о "среднем входе", средний вычисления вывода / времени выполнения могут быть бессмысленными. Если вы ожидаете равномерно случайных входов, хотя, это полезно подумать!
  • амортизированный наихудший случай: если вы используете амортизированную структуру данных наихудшего случая, производительность гарантируется в пределах амортизированного наихудшего случая... в конце концов (даже если входы выбраны злым демоном, который знает все и пытается обмануть вас). Обычно мы используем это для анализа алгоритмов, которые могут быть очень "прерывистыми" в производительности с неожиданные большие икоты, но со временем выполняют так же хорошо, как и другие алгоритмы. (Однако, если ваша структура данных не имеет верхних пределов для большой выдающейся работы, которую она готова откладывать, злой злоумышленник, возможно, заставит вас догнать максимальное количество прокрастинированной работы сразу.

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

как средний случай, так и амортизация-невероятно полезные инструменты для мышления и проектирования с учетом масштабирования.

(см. разница между средним случаем и амортизированным анализом если вас интересует эта подтема.)


Многомерная Биг-о

большую часть времени люди не понимают, что на работе больше одной переменной. Например, в string-алгоритм поиска, ваш алгоритм может занять время O([length of text] + [length of query]), т. е. он линейный в двух переменных, таких как O(N+M). Другие, более наивные алгоритмы могут быть O([length of text]*[length of query]) или O(N*M). Игнорирование нескольких переменных является одним из наиболее распространенных упущений, которые я вижу в анализе алгоритмов, и может помешать вам при разработке алгоритма.


вся история

имейте в виду, что big-O-это не вся история. Вы можете резко ускорить некоторые алгоритмы, использующие кэширование, делая их кэш-забывчивыми, избегая узких мест, работая с ОЗУ вместо диска, используя распараллеливание или делая работу раньше времени-эти методы часто независимая порядка роста нотации "big-O", хотя вы часто увидите количество ядер в нотации "big-O" параллельных алгоритмов.

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

  • если вы сортируете что-то вроде 5 элементов, вы не хотите использовать speedy O(N log(N)) quicksort; вы хотите использовать сортировку вставки, которая хорошо работает на небольших входах. Эти ситуации часто возникают в алгоритмах "разделяй и властвуй", где вы разделяете проблему на все меньшие и меньшие подзадачи, такие как рекурсивная сортировка, быстрые преобразования Фурье или матрица мультипликационный.
  • если некоторые значения эффективно ограничены из-за какого-то скрытого факта (например, среднее человеческое имя мягко ограничено примерно 40 буквами, а человеческий возраст мягко ограничен примерно 150). Вы также можете наложить ограничения на свой ввод, чтобы эффективно сделать термины постоянными.

на практике даже среди алгоритмов, которые имеют одинаковую или аналогичную асимптотическую производительность, их относительная ценность может фактически определяться другими вещами, такими как: другие факторы производительности (quicksort и mergesort-оба O(N log(N)), но quicksort использует преимущества кэшей ЦП); соображения непроизводительности, такие как простота реализации; доступна ли библиотека и насколько авторитетна и поддерживается библиотека.

программы также будут работать медленнее на компьютере 500MHz против компьютера 2GHz. Мы действительно не рассматриваем это как часть границ ресурсов, потому что мы думаем о масштабировании с точки зрения ресурсов машины (например, за такт), а не за настоящая секунда. Однако есть похожие вещи, которые могут "тайно" влиять на производительность, например, работаете ли вы под эмуляцией или оптимизированный код компилятора или нет. Это может сделать некоторые основные операции более длительными (даже относительно друг друга) или даже ускорить или замедлить некоторые операции асимптотически (даже относительно друг друга). Эффект может быть небольшим или большим между различными реализацией и/или окружающей средой. Вы переключаете языки или машины, чтобы eke out, что немного дополнительной работы? Это зависит от сотни других причин (необходимость, навыки, коллеги, производительность программиста, денежная стоимость вашего времени, знакомство, обходные пути, почему не сборка или GPU и т. д...), что может быть важнее производительности.

вышеупомянутые проблемы, как и язык программирования, почти никогда не рассматриваются как часть постоянного фактора (и не должны быть); но их следует знать, потому что иногда (хоть и редко) они могут влиять на вещи. Например, в cpython собственная реализация очереди приоритетов асимптотически неоптимальна (O(log(N)), а не O(1) для вашего выбора вставки или find-min); вы используете другую реализацию? Вероятно, нет, поскольку реализация C, вероятно, быстрее, и, вероятно, есть другие подобные проблемы в другом месте. Есть компромиссы; иногда они имеют значение, а иногда нет.--112-->


( edit: "простой английский" объяснение закончиться здесь.)

математические дополнения

для полноты точное определение обозначения big-O выглядит следующим образом:f(x) ∈ O(g(x)) означает, что "f асимптотически ограничен сверху const*g": игнорируя все, что ниже некоторого конечного значения x, существует постоянная такая, что |f(x)| ≤ const * |g(x)|. (Другие символы следующие: так же, как O означает,≤, Ω значит ≥. Существуют строчные варианты:o означает ω средства >.) f(x) ∈ Ɵ(g(x)) означает f(x) ∈ O(g(x)) и f(x) ∈ Ω(g(x)) (верхняя и нижняя границы g): существуют некоторые константы, такие что f всегда будет лежать в "полосе" между const1*g(x) и const2*g(x). Это самое сильное асимптотическое утверждение, которое вы можете сделать, и примерно эквивалентно ==. (Извините, я решил отложить упоминание символов абсолютной ценности до сих пор, для ясности; особенно потому, что я никогда не видел отрицательных значений в компьютерной науке контекст.)

люди часто будут использовать = O(...), что, возможно, является более правильным обозначением "comp-sci" и полностью законным для использования... но надо понимать = не используется как равенство; это составная нотация, которую следует читать как идиому. Меня учили использовать более строгие ∈ O(...). означает "является элементом". O(N²) на самом деле эквивалентности класс, то есть, это набор вещей, которые мы считаем одинаковыми. В данном конкретном случае, O(N²) содержит такие элементы, как {2 N², 3 N², 1/2 N², 2 N² + log(N), - N² + N^1.9, ...} и бесконечно велик, но это все еще набор. The = нотация может быть более распространенным, и даже используется в работах всемирно известных ученых-компьютерщиков. Кроме того, часто бывает так, что в случайной обстановке люди скажут O(...), когда они имеют в виду Ɵ(...); это технически верно, так как набор вещей Ɵ(exactlyThis) - это подмножество O(noGreaterThanThis)... и это легче печатать. ;-)


EDIT: быстрое Примечание, это почти наверняка запутывает Big O notation (который является верхней границей) с тета-нотацией (которая является как верхней, так и нижней границей). По моему опыту, это на самом деле типично для дискуссий в неакадемических условиях. Прошу прощения за возникшую путаницу.

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

очевидно, что это только использование "size" в качестве ввода и "Time taken" как на выходе - та же идея применяется, если вы хотите поговорить об использовании памяти и т. д.

вот пример, где у нас есть N футболок, которые мы хотим высушить. Мы будем предположим невероятно быстро получить их в положении сушки (т. е. человеческое взаимодействие незначительно). Конечно, в реальной жизни это не так...

  • используя стиральную линию снаружи: предполагая, что у вас бесконечно большой задний двор, стирка высыхает за O(1) Время. Сколько вы имейте его, он получит такое же солнце и свежий воздух, поэтому размер не влияет на время высыхания.

  • использование сушилки: вы кладете 10 рубашек в каждую нагрузку,а затем они сделаны через час. (Игнорируйте фактические цифры здесь-они не имеют значения.) Так сушка 50 рубашек занимает о 5 раз покуда сушить 10 рубашек.

  • положить все в шкаф для проветривания: если мы положим все в одну большую кучу и просто позволим генералу тепло сделайте это, это займет много времени для средних рубашек, чтобы высохнуть. Я не хотел бы угадывать детали, но я подозреваю, что это, по крайней мере, O(N^2) - по мере увеличения нагрузки на стирку время сушки увеличивается быстрее.

одним из важных аспектов обозначения "big O" является то, что это не сказать, какой алгоритм будет быстрее для данного размера. Возьмите hashtable (string key, integer value) против массива пар (string, integer). Быстрее ли найти ключ в hashtable или элемент в массиве, основанный на строке? (т. е. для массива " найдите первый элемент, где строковая часть соответствует заданному ключу.") Хэш-таблицы обычно амортизируются (~="в среднем") O (1) - после их настройки требуется примерно столько же времени, чтобы найти запись в таблице записей 100, как и в таблице записей 1,000,000. Поиск элемента в массиве (на основе содержимого, а не индекса) является линейным, т. е. O ( N) - в среднем вам придется смотреть на половину вступления.

делает ли это хэш-таблицу быстрее, чем массив для поиска? Необязательно. Если у вас очень небольшая коллекция записей, массив может быть быстрее - вы можете проверить все строки за время, необходимое для вычисления хэш-кода того, на который вы смотрите. Однако по мере увеличения набора данных хэш-таблица в конечном итоге побьет массив.


Big O описывает верхний предел поведения роста функции, например время выполнения программы, когда входные данные становятся большими.

примеры:

  • O( n): если я удвою размер ввода, среда выполнения удваивается

  • O (n2): если размер входного сигнала удваивает время выполнения в четыре раза

  • O (log n): если размер входного сигнала удваивается, время выполнения увеличивается на один

  • O (2n): если размер входного сигнала увеличивается на единицу, время выполнения удваивается

размер ввода обычно представляет собой пространство в битах, необходимое для представления ввода.


Big O notation чаще всего используется программистами в качестве приблизительной меры того, сколько времени потребуется для завершения вычисления (алгоритма), выраженного как функция размера входного набора.

Big O полезно сравнить, насколько хорошо два алгоритма будут масштабироваться по мере увеличения количества входов.

точнее Big O notation используется для выражения асимптотического поведения функции. Это значит, как функция ведет себя по мере приближения бесконечность.

во многих случаях "O" алгоритма попадает в один из следующих случаев:

  • O (1) - время завершения одинаково независимо от размера входного набора. Примером является доступ к элементу массива по индексу.
  • O (Log N) - время завершения увеличивается примерно в соответствии с log2 (n). Например, 1024 элемента занимает примерно в два раза больше времени, чем 32 элемента, потому что Log2(1024) = 10 и Log2(32) = 5. - пример-поиск элемента в бинарное дерево поиска (BST).
  • O (N) - время для завершения линейного масштабирования с размером входного набора. Другими словами, если вы удвоите количество элементов во входном наборе, алгоритм займет примерно вдвое больше времени. Пример подсчета количества элементов в связанном списке.
  • O (N Log N) - время завершения увеличивается на количество элементов, умноженное на результат Log2 (N). - пример куча вроде и быстрая сортировка.
  • O (N^2) - время завершения примерно равно квадрату количества элементов. Примером этого является сортировка.
  • O (N!) - время-это факториал входной набор. Примером этого является решение проблемы коммивояжера грубой силы.

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


Big O-это просто способ" выразить "себя обычным способом:" сколько времени / пространства требуется для запуска моего кода?".

вы можете часто видеть O(n), O (N2), O (nlogn) и так далее, все это просто способы показать; как изменяется алгоритм?

O (n) означает, что большое O равно n, и теперь вы можете подумать: "что такое n!?"Ну "N" - это количество элементов. Изображения вы хотите найти элемент в массиве. Вам придется смотреть на каждый элемент и как "вы правильный элемент / элемент?"в худшем случае элемент находится на последнем индексе, что означает, что он занял столько времени, сколько есть элементов в списке, поэтому, чтобы быть общим, мы говорим: "о, Эй, n-это справедливое заданное количество значений!".

тогда вы можете понять, что " n2" означает, но, чтобы быть еще более конкретным, играть с мыслью, что у вас есть простой, самый простой из алгоритмов сортировки; bubblesort. Этот алгоритм должен просматривать весь список, для каждого пункт.

мой список

  1. 1
  2. 6
  3. 3

поток здесь будет:

  • сравните 1 и 6, что самое большое? Ok 6 находится в правильном положении, двигаясь вперед!
  • сравните 6 и 3, О, 3 меньше! Давайте переместим это, хорошо, список изменился,нам нужно начать с самого начала!

Это O N2 потому что вам нужно посмотреть все элементы в списке есть "n" элементов. Для каждого элемента вы смотрите на все элементы еще раз, для сравнения, это также "n", поэтому для каждого элемента вы смотрите" N " раз, что означает n*n = n2

Я надеюсь, что это так просто, как вы хотите его.

но помните, что Big O-это просто способ испытать себя на манере времени и пространства.


Big O описывает фундаментальный масштабирующий характер алгоритма.

существует много информации, что Big O не говорит вам о данном алгоритме. Он режет до костей и дает только информацию о масштабирующем характере алгоритма, в частности о том, как использование ресурсов (время мышления или память) алгоритма масштабируется в ответ на "размер ввода".

рассмотрим разницу между паровым двигателем и ракетой. Они не просто различные разновидности одного и того же (как, скажем, двигатель Prius против двигателя Lamborghini), но они представляют собой совершенно разные виды двигательных систем, по своей сути. Паровой двигатель может быть быстрее игрушечной ракеты, но ни один паровой поршневой двигатель не сможет достичь скорости орбитальной ракеты-носителя. Это связано с тем, что эти системы имеют различные характеристики масштабирования в отношении соотношения топлива, необходимого ("использование ресурсов") для достижения заданной скорости ("вход размер.)"

Почему это так важно? Потому что программное обеспечение имеет дело с проблемами, которые могут отличаться по размеру факторы до триллиона. Подумайте об этом. Соотношение между скоростью, необходимой для путешествия на Луну, и скоростью ходьбы человека составляет менее 10 000:1, и это абсолютно крошечное по сравнению с диапазоном входных размеров программного обеспечения. И поскольку программное обеспечение может столкнуться с астрономическим диапазоном входных размеров, существует потенциал для большой сложности алгоритма, это фундаментальный масштабирующий характер, чтобы превзойти любые детали реализации.

рассмотрим типичный пример сортировки. Пузырьковая сортировка-O (n2) в то время как merge-sort-O(N log n). Предположим, у вас есть два приложения сортировки, приложение A, которое использует bubble-sort и приложение B, которое использует merge-sort, и предположим, что для входных размеров около 30 элементов приложение A на 1,000 x быстрее, чем приложение B при сортировке. Если вам никогда не нужно сортировать гораздо больше, чем 30 элементов, то это очевидно, что вы должны предпочесть приложение A, так как оно намного быстрее при этих размерах ввода. Однако, если вы обнаружите, что вам, возможно, придется сортировать десять миллионов элементов, то вы ожидаете, что приложение B на самом деле окажется в тысячи раз быстрее, чем приложение A в этом случае, полностью из-за того, как каждый алгоритм масштабируется.


вот простой английский бестиарий, который я обычно использую при объяснении распространенных разновидностей Big-O

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

O (1):

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

O (log n):

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

O (n):

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

O (n log n):

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

O (n2):

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

O (2n):

не масштабируется. У вас нет надежды решить какую-либо проблему нетривиального размера. Полезно знать, чего избегать, и для экспертов найти приближенные алгоритмы, которые находятся в O (nk).


Big O-это мера того, сколько времени / пространства использует алгоритм относительно размера его ввода.

если алгоритм равен O (n), то время/пространство будет увеличиваться с той же скоростью, что и его вход.

если алгоритм равен O (n2) затем время / пространство увеличивается со скоростью его ввода в квадрат.

и так далее.


очень трудно измерить скорость программных программ, и когда мы пытаемся, ответы могут быть очень сложными и заполнены исключениями и специальными случаями. Это большая проблема, потому что все эти исключения и особые случаи отвлекают и бесполезны, когда мы хотим сравнить две разные программы друг с другом, чтобы узнать, какая из них "самая быстрая".

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

если Вы читаете " о "как значение" в порядке " или "приблизительно", вы не ошибетесь. (Я думаю, что выбор Big-Oh мог быть попыткой юмора).

единственное, что пытаются сделать эти выражения "Big-Oh", - это описать, насколько программное обеспечение замедляется по мере увеличения объема данных, которые программное обеспечение должно обрабатывать. Если мы удваиваем объем данных, которые необходимо обработать, требуется ли программное обеспечение в два раза больше времени для завершения это работа? В десять раз дольше? На практике существует очень ограниченное количество выражений big-Oh, с которыми вы столкнетесь и о которых нужно беспокоиться:

хорошо:

  • O(1) постоянный: программа занимает то же время для запуска независимо от того, насколько велик вход.
  • O(log n) логарифмические: время выполнения программы увеличивается только медленно, даже с большим увеличением размера ввода.

в плохо:

  • O(n) линейный: время выполнения программы увеличивается пропорционально размеру входного сигнала.
  • O(n^k) многочлена: - время обработки растет быстрее и быстрее - как полиномиальная функция-по мере увеличения размера ввода.

... и уродливый:

  • O(k^n) экспоненциальный время выполнения программы увеличивается очень быстро с даже умеренным увеличением размер задачи-это только практично обрабатывать небольшие наборы данных с экспоненциальными алгоритмами.
  • O(n!) факторный время выполнения программы будет больше, чем вы можете позволить себе ждать чего-либо, кроме самых маленьких и самых тривиальных наборов данных.

что такое простое английское объяснение Big O? С как можно меньшим формальным определением и простой математикой.

простое объяснение нужно для обозначения Big-O:

когда мы программируем, мы пытаемся решить проблему. Что нам код называется алгоритм. Big O notation позволяет нам сравнивать худшую производительность наших алгоритмов стандартизированным способом. Спецификации оборудования меняют над временем и улучшения в оборудовании могут сократить время, необходимое для запуска алгоритмов. Но замена оборудования не означает, что наш алгоритм лучше или улучшается с течением времени, так как наш алгоритм все тот же. Поэтому, чтобы позволить нам сравнить различные алгоритмы, чтобы определить, является ли один лучше или нет, мы используем Big O notation.

простое объяснение что большой o обозначение:

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


простой прямой ответ может быть:

Big O представляет наихудшее возможное время / пространство для этого алгоритма. Алгоритм никогда не будет занимать больше пространства/времени выше этого предела. Big O представляет сложность времени/пространства в крайнем случае.


хорошо, мои 2cents.

Big-O, is


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

когда мы говорим, что некоторый алгоритм O(f (n)), мы говорим, что время работы(или пространство, необходимое) для этого алгоритма всегда ниже, чем некоторые постоянные времена f (n).

сказать, что двоичный поиск имеет время работы O (logn), чтобы сказать, что существует некоторая константа c, которую вы можете умножить log(n) на то, что всегда будет больше, чем время работы двоичного поиска. В этом случае вы всегда будете иметь некоторый постоянный коэффициент сравнения log(n).

другими словами, где g(n) - время работы вашего алгоритма, мы говорим, что g(n) = O(f(n)), когда g(n) k, где c и k-некоторые константы.


"что такое простое английское объяснение Big O? С формальной определение как можно более простое и математическое."

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

Big O notation просто говорит, сколько времени * алгоритм может работать в пределах, в терминах только количество входных данные**.

( *в замечательной, unit-free чувство времени!)
(**что имеет значение, потому что люди будут всегда хочу больше, живут ли они сегодня или завтра)

Ну, что такого замечательного в большой o-нотации, если это то, что она делает?

  • практически говоря, большой анализ O так полезно и важно потому что большой O ставит фокус прямо на алгоритм собственные сложность и полностью игнорировать все, что является просто константой пропорциональности - например, движок JavaScript, скорость процессора, подключение к Интернету и все те вещи, которые быстро становятся такими же смехотворно устаревшими, как модель T. Big O фокусируется на производительности только таким образом, который одинаково важен для людей, живущих в настоящем или будущем.

  • большой o обозначения также светит обратите внимание непосредственно на самый важный принцип компьютерного программирования / инженерии, тот факт, который вдохновляет всех хороших программистов продолжать думать и мечтать: единственный способ достичь результатов за пределами медленного продвижения вперед технологии является изобрести лучший алгоритм.


пример алгоритма (Java):

// given a list of integers L, and an integer K
public boolean simple_search(List<Integer> L, Integer K)
{
    // for each integer i in list L
    for (Integer i : L)
    {
        // if i is equal to K
        if (i == K)
        {
            return true;
        }
    }

    return false;
}

описание алгоритма:

  • этот алгоритм поиска списка, пункт за пунктом, ищет ключ,

  • итерация по каждому элементу в списке, если это ключ, то верните True,

  • если цикл закончился, не найдя ключ, верните False.

Big-O обозначения представляют верхняя граница сложности (время, пространство,..)

чтобы найти Big-O по сложности времени:

  • вычислите, сколько времени (относительно размера ввода) занимает худший случай:

  • в худшем случае: ключ не существует в списке.

  • время (в худшем случае) = 4n+1

  • время: O (4n+1) = O | n) / в Big-O константы забытый

  • O (n) ~ линейный

есть также Big-Omega, которые представляют сложность в лучшем случае:

  • в лучшем случае: ключ является первым элементом.

  • Время (В Лучшем Случае) = 4

  • Время: Ω(4) = O (1) ~ Мгновенное\Постоянное


Big O

f(x) = O(g(x)) когда x переходит в a (например, A=+∞) означает, что существует функция k такое, что:

  1. f(x)=k(x)g(x)

  2. k ограничено в некоторой окрестности a (если a = +∞, это означает, что существуют числа N и M такие, что для каждого x > N,|k(x) /

другими словами, на простом английском языке:f(x) = O(g(x)), x → a, означает, что в окрестности a f разлагается в произведение g и некоторая ограниченная функция.

Малая o

кстати, вот для сравнения определение малого o.

f(x) = o(g(x)) когда x переходит к A означает, что существует функция k такая что:

  1. f(x)=k(x)g(x)

  2. k(x) переходит в 0, когда x переходит в a.

примеры

  • sin x = O (x), когда x → 0.

  • sin x = O (1), Когда x→+∞,

  • x2 + x = O (x), когда x → 0,

  • x2 + x = O(x2) при x → +∞,

  • ln(x) = o(x) = O (x), когда x → +∞.

внимание! обозначение со знаком равенства " = "использует" поддельное равенство": верно, что o(g(x)) = O(g(x)), но ложно, что O(g(x)) = o(g(x)). Аналогично, можно написать " ln(x) = o (x), когда X→ +∞", но формула "o (x) = ln( x)" не будет чувство.

примеры

  • O (1) = O(n) = O(N2) когда n → + ∞ (но не наоборот, равенство "поддельное"),

  • O(n) + O (N2) = O (n2) при n → +∞

  • O (O (n2)) = O (n2) при n → +∞

  • O (n2) O (n3) = O (n5) при n → +∞


вот статья Википедии:https://en.wikipedia.org/wiki/Big_O_notation


Big O notation-это способ описания того, как быстро алгоритм будет работать с произвольным количеством входных параметров, которые мы будем называть "n". Это полезно в информатике, потому что разные машины работают на разных скоростях, и просто сказать, что алгоритм занимает 5 секунд, не говорит вам многого, потому что, хотя вы можете работать с системой с октоядерным процессором 4,5 ГГц, я могу работать с 15-летней системой 800 МГц, которая может занять больше времени независимо от алгоритма. Так вместо того чтобы указывать, как быстро алгоритм работает во времени, мы говорим, как быстро он работает с точки зрения количества входных параметров или "n". Описывая алгоритмы таким образом, мы можем сравнивать скорости алгоритмов без необходимости учитывать скорость самого компьютера.


Не уверен, что я в дальнейшем вкладываю в эту тему, но все же думал, что поделюсь: я когда-то нашел этот блог иметь некоторые довольно полезные (хотя и очень простые) объяснения и примеры на Big O:

через примеры это помогло получить голые основы в мой черепаховый череп, поэтому я думаю, что это довольно 10-минутное чтение, чтобы вы направились в правильном направлении.


вы хотите знать все, что нужно знать о big O? И я тоже.--1-->

поэтому, чтобы говорить о big O, я буду использовать слова, которые имеют только один удар в них. Один звук на слово. Маленькие слова быстры. Вы знаете эти слова, как и я. мы будем использовать слова с одним звуком. Они маленькие. Я уверен, что вы знаете все слова, которые мы будем использовать!

теперь давай поговорим о работе. Большую часть времени, я не люблю работать. Ты любишь работать? Может быть, так оно и есть, но я ... конечно, нет.

Я не люблю ходить на работу. Я не люблю проводить время на работе. Будь моя воля, я бы просто играл и развлекался. Ты чувствуешь то же, что и я?

теперь время от времени мне нужно идти на работу. Это печально, но это правда. Поэтому, когда я на работе, у меня есть правило: я стараюсь делать меньше работы. Как можно ближе к работе. Тогда я иду играть!

Итак, вот большие новости: большой O может помочь мне не делать работу! Я могу играть больше времени, если я знать big O. меньше работы, больше игры! Это то, что большой О помогает мне делать.

теперь у меня есть работа. У меня есть список: раз, два, три, четыре, пять, шесть. Я должен добавить все в этот список.

Вау, я ненавижу работу. Но я должна это сделать. И вот я здесь.

один плюс два-три ... плюс три-шесть... и четыре... Я не знаю. Я заблудился. Это слишком трудно для меня сделать в моей голове. Мне не очень нравится такая работа.

Так давайте не будем выполнять работу. Давай просто подумаем, как это тяжело. Сколько работы мне придется сделать, чтобы сложить шесть чисел?

Ну, давайте посмотрим. Я должен сложить один и два, а потом сложить это с тремя, а потом сложить это с четырьмя... В общем, я насчитал шесть сложений. Я должен сделать шесть добавлений, чтобы решить эту проблему.

вот идет большой O, чтобы рассказать нам, насколько сложна эта математика.

Big O говорит: Мы должны сделать шесть добавлений, чтобы решить эту проблему. По одной добавке на каждую вещь от одного до шести. Шесть маленьких кусочков работа... каждый бит работы - это одно дополнение.

Ну, я не буду делать работу, чтобы добавить их. Но я знаю, как это будет трудно. Это будет шесть добавлений.

О нет, теперь у меня больше работы. Шиш. Кто делает такие вещи?!

теперь они просят меня добавить от одного до десяти! Зачем мне это делать? Я не хотел добавлять один к шести. Добавить от одного до десяти ... ну... это было бы еще труднее!

насколько сложнее это будет? Сколько еще я буду работать? должен? Мне нужно больше или меньше шагов?

ну, я думаю, мне придется сделать десять добавлений... по одному для каждой вещи от одного до десяти. Десять больше, чем шесть. Мне пришлось бы работать, чтобы добавить от одного до десяти, а не от одного до шести!

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

чтобы добавить от одного до шести, это некоторая работа. Но видите ли, если прибавить от одного до десяти, что больше работы?

Big O-твой и мой друг. Big O помогает нам думать о том, сколько работы мы должны сделать, чтобы мы могли планировать. И, если мы дружим с big O, он может помочь нам выбрать работу, которая не так сложна!

теперь мы должны сделать новую работу. О, нет. Мне совсем не нравится эта работа.

новая работа: добавьте все вещи от одного до n.

подождите! Что такое Н? Я пропустил это? Как я могу добавить от одного до n, если вы не скажете мне, что n есть?

Ну, я не знаю, что такое n. Мне не сказали. А ты? Нет? Ну что ж. Так что мы не можем работать. Вот так так.

но хотя мы не будем делать работу сейчас, мы можем догадаться, как трудно было бы, если бы мы знали n. Мы должны сложить n вещей, верно? Конечно!

теперь идет большой О, и он расскажет нам, как тяжела эта работа. Он говорит: добавлять все от одного к N, одно за другим, - Это O(n). Чтобы добавить все это, [я знаю, что должен добавить n раз.][1], что большой О! Он говорит нам, как трудно выполнять какую-то работу.

для меня, я думаю о большой о большой, медленный, босс. Он думает о работе, но не делает этого. Он может сказать: "эта работа быстрая. Или он мог бы сказать: "эта работа такая медленная и тяжелая!- Но он не делает эту работу. Он просто смотрит на работу, а потом говорит нам, сколько времени это может занять.

Я много забочусь о большом О. почему? Я не люблю работать! Никто не любит работать. Вот почему мы все любим big O! Он говорит нам, как быстро мы можем работать. Он помогает нам думать о том, как тяжела работа.

ох, больше работы. Давай не будем работать. Но давайте составим план, шаг за шагом.

Ergh. Похоже, много работы!

Как мы можем сортировать эту колоду? У меня есть план.

Я буду смотреть на каждого пара карт, пара за парой, через колоду, от первой до последней. Если первая карта в одной паре большая, а следующая в этой паре маленькая, я меняю их местами. В противном случае я иду к следующей паре, и так далее, и так далее... и вскоре колода готова.

когда колода закончена, я спрашиваю: я поменял карты в этом проходе? Если так, я должен сделать это еще раз, с самого начала.

в какой-то момент, в какое-то время, не будет никаких свопов, и наш вид колоды будет сделано. Так сильно работать!

Ну, сколько работы это будет, чтобы отсортировать карты с этими правилами?

У меня есть десять карт. И большую часть времени-то есть, если мне не повезет-я должен пройти всю колоду до десяти раз, каждый раз меняя местами до десяти карт.

Big O, помогите мне!

входит большой O и говорит: для колоды из n карт, сортировать ее таким образом будет сделано в O(N в квадрате) времени.

Почему он говорит n в квадрате?

Ну, вы знаете, что N в квадрате-это n раз n. Теперь я понимаю: N карт проверены, вплоть до того, что может быть n раз через колоду. Это две петли, каждая из которых имеет n шагов. Это N в квадрате много работы, которую нужно сделать. Много работы, конечно!

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

теперь вот где большой О-наш друг.

Big O указывает на это: когда n становится большим, когда мы сортируем карты, работа становится намного сложнее, чем старая работа "просто добавьте эти вещи". Откуда мы это знаем?

Ну, если n становится действительно большим, нам все равно, что мы можем добавить к N или N в квадрате.

для большого n квадрат N больше, чем n.

Big O говорит нам, что сортировать вещи сложнее, чем добавлять вещи. O (n в квадрате) больше чем O (n) для большого n. Это означает: если n становится действительно большим, для сортировки смешанной колоды из n вещей должно потребоваться больше времени, чем просто добавить N смешанных вещей.

Big O не решает работу за нас. Большой О говорит нам, как тяжела работа.

У меня есть колода карт. Я их сортировал. Ты помог. Спасибо.

есть ли более быстрый способ сортировки карт? Большой О может нам помочь?

Да, есть более быстрый путь! Чтобы научиться, нужно время, но это работает... и это работает довольно быстро. Вы тоже можете попробовать, но не торопитесь с каждым шагом и не теряйте свое место.

в этом новом способе сортировки колоды, мы не проверяем пары карт, как мы сделали некоторое время назад. Вот ваши новые правила сортировки этой колоды:

один: я выбираю одну карту в той части колоды, над которой мы сейчас работаем. Можешь выбрать для меня, если хочешь. (Первый раз мы делаем это, "часть колоды мы работаем сейчас" - это вся колода, конечно.)

Два: I выложите колоду на карту, которую выбрали. Что это за шлейф, как я шлейфую? Ну, я иду от стартовой карты вниз, одну за другой, и я ищу карту, которая выше, чем карта splay.

три: я иду от конечной карты вверх, и я ищу карту, которая ниже, чем карта splay.

Как только я нашел эти две карты, я меняю их и продолжаю искать другие карты для обмена. То есть, я возвращаюсь ко второму шагу и раскладываю на карте, которую вы выбрали больше.

в какой-то момент, этот цикл (от двух до трех) закончится. Он заканчивается, когда обе половины этого поиска встречаются на карте splay. Затем мы просто разложили колоду с картой, которую вы выбрали на первом шаге. Теперь все карты в начале ниже, чем карта splay; и карты в конце выше, чем карта splay. Классный трюк!

четыре (и это забавная часть): теперь у меня есть две маленькие колоды, одна более низкая, чем карта splay, и одна более высокая. Теперь Я перейти к шагу один, на каждой маленькой палубе! То есть я начинаю с первой ступени на первой маленькой палубе, а когда эта работа сделана, я начинаю с первой ступени на следующей маленькой палубе.

Как называется этот сорт? Это называется быстрая сортировка! Этот сорт был сделан человеком по имени К. А. Р. Хоар и он назвал это быстрая сортировка. Теперь, быстрая сортировка используется все время!

быстрая сортировка разбивает большие колоды на маленькие. То есть он разбивает большие задачи на маленькие.

Хммм. Думаю, там есть какое-то правило. Чтобы сделать большие задачи маленькими, разбейте их.

этот вид довольно быстро. Как быстро? Big O говорит нам: этот вид должен O (N log n) работать сделано, в среднем случае.

Это более или менее быстрый, чем первый? Большой O, пожалуйста, помогите!

первый сорт был O (N в квадрате). Но быстрая сортировка-O (N log n). Вы знаете, что N log n меньше, чем N в квадрате, для большого n, верно? Вот откуда мы знаем, что быстрая сортировка-это быстрая!

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

Почему я выбираю быструю сортировку? Мне не нравится работать, конечно! Я хочу, чтобы работа была сделана как можно скорее.

Как узнать, что быстрый сортировка меньше работы? Я знаю, что O(N log n) меньше O(N в квадрате). O более маленькие, поэтому быстрая сортировка меньше работы!

теперь вы знаете моего друга, большого О. Он помогает нам делать меньше работы. И если вы знаете big O, вы можете сделать меньше работы тоже!

вы узнали все это со мной! Ты такой умный! Большое вам спасибо!

теперь, когда работа сделана, пойдем Играй!


[1]: есть способ обмануть и добавить все вещи от одного до n, все за один раз. Мальчик по имени Гаусс узнал об этом, когда ему было восемь. Я не настолько умен, так что не спрашивайте меня, как он это сделал.


Предположим, мы говорим об алгоритме A, который должен что-то делать с набором данных в размере n.

затем O( <some expression X involving n> ) значит, на простом английском языке:

Если вам не повезло при выполнении A, может потребоваться x(n) операций для полный.

как это происходит, есть определенные функции (думать о них как реализации of X (n)), что, как правило, происходят довольно часто. Это хорошо известен и легко сравнивается (примеры:1, Log N, N, N^2, N!, etc..)

сравнивая их, когда речь идет о A и другие алгоритмы, легко ранжировать алгоритмы в соответствии с количеством операций, которые они мая (в худшем случае) требуют по полной.

в общем, нашей целью будет найти или структура алгоритма A таким образом, что он будет иметь функцию X(n) что возвращается как можно меньше.


у меня более простой способ понять сложность времени наиболее распространенной метрикой для вычисления сложности времени является Big O notation. Это удаляет все постоянные факторы, так что время выполнения может быть оценено относительно N, поскольку N приближается к бесконечности. В общем, вы можете думать об этом так:

statement;

постоянна. Время работы оператора не изменится по отношению к N

for ( i = 0; i < N; i++ )
  statement;

линейный. Время выполнения цикла прямо пропорционально к N. Когда N удваивается, так же как и время работы.

for ( i = 0; i < N; i++ ) 
{
for ( j = 0; j < N; j++ )
  statement;
}

квадратичная. Время работы двух петель пропорционально квадрату N. Когда N удваивается, время работы увеличивается на N * N.

while ( low <= high ) 
{
 mid = ( low + high ) / 2;
 if ( target < list[mid] )
 high = mid - 1;
 else if ( target > list[mid] )
  low = mid + 1;
else break;
}

логарифмическая. Время работы алгоритма пропорционально количеству раз, когда N можно разделить на 2. Это связано с тем, что алгоритм делит рабочую область пополам с каждой итерацией.

void quicksort ( int list[], int left, int right )
{
  int pivot = partition ( list, left, right );
  quicksort ( list, left, pivot - 1 );
  quicksort ( list, pivot + 1, right );
}

Is N * log (N ). Время выполнения состоит из N циклов (итерационных или рекурсивных), которые являются логарифмическими, таким образом, алгоритм представляет собой комбинацию линейного и логарифмического.

В общем, делать что-то с каждым элементом в одном измерении линейно, делать что-то с каждым элементом в двух измерениях квадратично, а деление рабочей области пополам логарифмично. Есть и другие большие меры O, такие как кубический, экспоненциальный и квадратный корень, но они не так распространены. Обозначение Big O описывается как O (), где мера. Алгоритм quicksort будет описан как O ( N * log (N ) ).

Примечание: ничто из этого не учитывало лучшие, средние и худшие меры. У каждого будет своя большая буква "О". Также обратите внимание, что это очень упрощенное объяснение. Big O является наиболее распространенным, но это также более сложно, что я показал. Есть и другие обозначения, такие как большая омега, маленькая О и большая тета. Вы, вероятно,не столкнетесь с ними вне курса анализа алгоритмов.


скажем, вы заказываете Harry Potter: Complete 8-Film Collection [Blu-ray] от Amazon и одновременно загружаете ту же коллекцию фильмов онлайн. Вы хотите проверить, какой метод быстрее. Доставка занимает почти сутки, чтобы прибыть и загрузка завершена примерно на 30 минут раньше. Здорово! Так что это напряженная гонка.

Что, если я закажу несколько фильмов Blu-ray, таких как "Властелин колец", "Сумерки", трилогия "Темный рыцарь" и т. д. и скачать все фильмы онлайн одновременно? Этот время, доставка по-прежнему занимает день для завершения, но онлайн-загрузка занимает 3 дня. Для интернет-магазинов количество купленного товара (вход) не влияет на время доставки. Выход является постоянным. Мы называем это O (1).

для онлайн-загрузки время загрузки прямо пропорционально размеру файла фильма (вход). Мы называем это O (n).

из экспериментов мы знаем, что интернет-магазины Весов лучше, чем онлайн загрузка. Очень важно понять нотацию big O, потому что она помогает вам анализировать масштабируемость и эффективность алгоритмов.

Примечание: Big O обозначение представляет худший сценарий алгоритма. Предположим, что O (1) и O (n) являются наихудшими сценариями примера выше.

ссылка : http://carlcheo.com/compsci


Если у вас есть подходящее понятие бесконечности в вашей голове, то есть очень краткое описание:

Big O notation сообщает вам стоимость решения бесконечно большой проблемы.

и далее

постоянные факторы пренебрежимо малы

Если вы обновляетесь до компьютера, который может запускать ваш алгоритм в два раза быстрее, Big O notation этого не заметит. Постоянный фактор улучшения слишком малы, чтобы даже быть замечено в масштабе, с которым работает Big O notation. Обратите внимание, что это преднамеренная часть дизайна нотации big O.

хотя все, что" больше", чем постоянный фактор, может быть обнаружено, однако.

когда вы заинтересованы в выполнении вычислений, размер которых "достаточно велик", чтобы считаться приблизительно бесконечностью, тогда Big O notation-это приблизительно стоимость решения вашей проблемы.


Если вышеизложенное не имеет смысла, то у вас нет совместимое интуитивное понятие бесконечности в вашей голове, и вы, вероятно, должны игнорировать все вышеперечисленное; единственный способ, которым я знаю, чтобы сделать эти идеи строгими или объяснить их, если они еще не интуитивно полезны, - это сначала научить вас большой o нотации или что-то подобное. (хотя, как только вы хорошо поймете нотацию big O в будущем, возможно, стоит пересмотреть эти идеи)


самый простой способ посмотреть на него (на простом английском языке)

мы пытаемся увидеть, как количество входных параметров влияет на время работы алгоритма. Если время работы вашего приложения пропорционально количеству входных параметров, то говорят, что оно находится в большом O из n.

приведенное выше утверждение является хорошим началом, но не полностью истинным.

более точное объяснение (математический)

предположим

N=количество входных параметров

T (n)= фактическая функция, которая выражает время работы алгоритма как функцию n

c= константа

f (n)= приближенная функция, которая выражает время работы алгоритма как функцию n

тогда, что касается большого O, приближение f (n) считается достаточно хорошим, если приведенное ниже условие истинный.

lim     T(n) ≤ c×f(n)
n→∞

уравнение читается как Когда n приближается к бесконечности, T из n меньше или равно c раз f из n.

в обозначении big O это записывается как

T(n)∈O(n)

это читается как T из n в большом O из n.

на английском

основываясь на математическом определении выше, если вы говорите, что ваш алгоритм является большим O из n, это означает, что это функция n (количество входных параметров) или быстрее. Если ваш алгоритм большой O из n, тогда он также автоматически является большим o из N квадрата.

Big O of n означает, что мой алгоритм работает по крайней мере так же быстро, как это. Вы не можете смотреть на Big O notation вашего алгоритма и говорить его медленно. Вы можете только сказать, что это быстро.

Регистрация этой для видеоурока по Big O от UC Berkley. Это на самом деле простая концепция. Если вы услышите, как профессор Шучак (он же учитель уровня Бога) объясняет это, вы скажете: "О, это все есть!".


что такое простое английское объяснение обозначения "Big O"?

Очень Быстрое Примечание:

O в "большом O" означает " порядок "(или именно"порядок")
таким образом, вы можете получить его идею буквально, что он используется для заказа чего-то, чтобы сравнить их.

  • "Big O" делает две вещи:

    1. оценивает, сколько шагов метода ваш компьютер применяет для выполнения задача.
    2. облегчить процесс для сравнения с другими, чтобы определить, хорошо это или нет?
    3. "Большой О" достигает вышеуказанных 2 с унифицированным Notations.
  • есть семь наиболее часто используемых обозначений

    1. O (1), означает, что ваш компьютер выполняет задачу с помощью 1 шаг, это отлично, заказал № 1
    2. O (logN), означает, что ваш компьютер выполняет задачу с logN ступеньки, хорошо, заказал № 2
    3. O( N), завершите задачу с N ступеньки, своя ярмарка, приказ № 3
    4. O( NlogN), завершает задачу с O(NlogN) шаги, это не хорошо, заказ № 4
    5. O (N^2), выполните задачу с помощью N^2 шаги, плохо, приказ № 5
    6. O( 2^N), выполните задачу с помощью 2^N шаги, это ужасно, приказ № 6
    7. O (N!), получить задачу с N! шаги, это ужасно, заказ № 7

enter image description here

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

пожалуйста заметьте заказ на конце линии, как раз для вашего лучшего понимания.Существует более 7 обозначений, если учесть все возможности.

в CS набор шагов для выполнения задачи называется алгоритмы.
В терминологии, нотация Big-O используется для описания характеристик и сложности алгоритма.

кроме того, Big O устанавливает наихудший случай или измеряет шаги с верхней границей.
В лучшем случае вы можете обратиться к Big-Ω (Big-Omega).

Big-Ω (Big-Omega) обозначение (статья) / Академия Хана

  • резюме
    "Big O" описывает производительность алгоритма и оценить его.

    или обратиться к нему формально, "Big O" классифицирует алгоритмы и стандартизирует процесс сравнения.


Это очень упрощенное объяснение, но я надеюсь, что он охватывает наиболее важные детали.

предположим, что ваш алгоритм решения проблемы зависит от некоторых "факторов", например, давайте сделаем это N и X.

в зависимости от N и X ваш алгоритм потребует некоторых операций, например, в худшем случае это 3(N^2) + log(X) операции.

поскольку Big-O не слишком заботится о постоянном факторе (он же 3), Big-O вашего алгоритма -O(N^2 + log(X)). Это в основном переводит "количество операций, необходимых вашему алгоритму для наихудших масштабов с этим".


определение: - Big O notation-это нотация, которая говорит, как производительность алгоритма будет выполняться, если ввод данных увеличивается.

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

Я бы рекомендовал вам посмотреть это видео на youtube, которое объясняет Big O Notation подробно с примерами кода.

Algorithm basic pillars

предположим, например, что алгоритм принимает 5 записей, а время, необходимое для их обработки, составляет 27 секунд. Теперь, если мы увеличим записи до 10, алгоритм займет 105 секунд.

простыми словами время является квадратом числа записей. Мы можем обозначить это через O (n ^ 2). Это символическое представление называется Большим O обозначение.

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

Big O symbols

например, посмотрите на приведенную ниже функцию "Function1", которая принимает коллекцию и выполняет обработку первой записи. Теперь для этой функции производительность будет такой же независимо от того, ставите вы 1000, 10000 или 100000 записей. Таким образом, мы можем обозначить его O (1).

void Function1(List<string> data)
{
string str = data[0];
}

теперь см. приведенную ниже функцию " Function2 ()". В этом случае время обработки будет увеличиваться количество записей. Мы можем обозначить эту производительность алгоритма, используя O (n).

void Function2(List<string> data)
        {
            foreach(string str in data)
            {
                if (str == "shiv")
                {
                    return;
                }
            }
        }

когда мы видим большую нотацию O для любого алгоритма, мы можем классифицировать их по трем категориям производительности : -

  1. категория журнала и констант :- Любой разработчик хотел бы видеть их производительность алгоритма в этой категории.
  2. Linear: - разработчик не захочет видеть алгоритмы в этой категории, пока не останется последний вариант или единственный вариант.
  3. экспоненциальный: - это то, где мы не хотим видеть наши алгоритмы и необходима доработка.

поэтому, глядя на большие обозначения O, мы классифицируем хорошие и плохие зоны для алгоритмы.

Bog O classification

Я бы рекомендовал вам посмотреть это 10-минутное видео, в котором обсуждается Big O с образцом кода

https://www.youtube.com/watch?v=k6kxtzICG_g


Если я хочу объяснить это 6-летнему ребенку, я начну рисовать некоторые функции f(x) = x и f (x) = x^2, например, и спрошу ребенка, какая функция будет верхней функцией в верхней части страницы. Затем мы продолжим рисовать и видеть, что X^2 победы. "Кто победит" на самом деле является функцией, которая растет быстрее, когда x стремится к бесконечности. Таким образом," функция x находится в большом O x^2 " означает, что x растет медленнее, чем x^2, Когда x стремится к бесконечности. То же самое можно сделать, когда x стремится к 0. Если мы нарисуем это две функции для x от 0 до 1 x будут верхней функцией, поэтому "функция X^2 находится в большом O x для x стремится к 0". Когда ребенок станет старше, я добавлю, что действительно большой O может быть функцией, которая растет не быстрее, а так же, как данная функция. Более того, константа отбрасывается. Таким образом, 2x находится в большом O из x.