Что такое O (…) и как мне его рассчитать?


31

Помогите! У меня есть вопрос, где мне нужно проанализировать Big-O алгоритма или некоторый код.

  • Я не уверен точно, что такое Big-O или как оно связано с Big-Theta или другими средствами анализа сложности алгоритма.

  • Я не уверен, относится ли Big-O ко времени выполнения кода или к количеству памяти, которое ему требуется (компромиссы между пространством и временем).

  • У меня есть домашнее задание по информатике, где мне нужно взять несколько циклов, возможно, рекурсивный алгоритм, и придумать для этого Big-O.

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

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

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


1
Просто примечание, этот вопрос обсуждается здесь .
enderland

2
Большим ресурсом для начала был бы курс академии Хана (один из авторов - Томас Кормен из CLRS). Это был большой ресурс для меня как выпускника CS тоже. khanacademy.org/computing/computer-science/algorithms
Судип Бхандари

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

Ответы:


22

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

В нотации Big-O стоимость алгоритма представлена ​​его самой дорогой операцией при больших числах. Если алгоритм предпринимает шаги, он будет представлен O (n 3 ). Алгоритм, который подсчитывает каждый элемент в списке, будет работать за O (n) время, называемое линейным временем.n3 + n2 + n

Для списка имен и классических примеров в Википедии: Заказы общих функций

Материалы по теме:


6
Примечание: большой O не измеряет время, пространство или какую-то конкретную вещь. Это просто верхняя граница асимптотического роста функции (до константы). Эта функция может быть временем, пространством и т. Д. Алгоритма в зависимости от его входной длины, и чаще всего в контексте CS это время, но не обязательно.
Восстановить Монику

23

Каковы асимптотические функции? Что такое асимптота?

Учитывая функцию f (n), которая описывает количество ресурсов (процессорного времени, оперативной памяти, дискового пространства и т. Д.), Потребляемых алгоритмом при применении к входу размером n , мы определяем до трех асимптотических обозначений для описания его производительности для большая п .

Асимптота (или асимптотическая функция) - это просто некоторая другая функция (или отношение) g (n), к которой f (n) становится все ближе по мере того, как n растет все больше и больше, но никогда не достигает. Преимущество разговоров об асимптотических функциях состоит в том, что о них, как правило, гораздо проще говорить, даже если выражение для f (n) чрезвычайно сложно. Асимптотические функции используются как часть ограничительных обозначений, которые ограничивают f (n) выше или ниже.

(Примечание: в используемом здесь смысле асимптотические функции близки к исходной функции только после исправления некоторого постоянного ненулевого множителя, так как все три обозначения big-O / Θ / Ω игнорируют эти постоянные факторы из их рассмотрения.)

Каковы три асимптотические ограничивающие нотации и чем они отличаются?

Все три обозначения используются следующим образом:

f (n) = O (g (n))

где f (n) здесь - интересующая функция, а g (n) - некоторая другая асимптотическая функция, которой вы пытаетесь аппроксимировать f (n) . Это не должно восприниматься как равенство в строгом смысле, но формальное утверждение о том, как быстро f (n) растет относительно n по сравнению с g (n) , когда n становится большим. Пуристы часто используют альтернативные обозначения f (n) ∈ O (g (n)), чтобы подчеркнуть, что символ O (g (n)) действительно представляет собой целое семейство функций, которые имеют общую скорость роста.

Обозначение Big-ϴ (Theta) утверждает равенство при росте f (n) до постоянного множителя (подробнее об этом позже). Он ведет себя аналогично =оператору по темпам роста.

Обозначение Big-O описывает верхнюю границу роста f (n) . Он ведет себя аналогично оператору по темпам роста.

Обозначение Big Ω (Omega) описывает нижнюю границу роста f (n) . Он ведет себя аналогично оператору по темпам роста.

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

Обозначения Big-O и подобные им часто служат способом сравнения сложности времени .

Что такое сложность времени?

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

Также часто говорят о сложности пространства, используя обозначение Big-O. Сложность пространства - это объем памяти (хранилища), необходимый для завершения алгоритма, который может быть ОЗУ, диском и т. Д.

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

Расчет Big-ϴ

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

Дана функция f (n) в псевдокоде:

int f(n) {
  int x = 0;
  for (int i = 1 to n) {
    for (int j = 1 to n) {
      ++x;
    }
  }
  return x;
}

Какова сложность времени?

Внешний цикл выполняется n раз. Каждый раз, когда работает внешний цикл, внутренний цикл выполняется n раз. Это ставит время работы на T (n) = n 2 .

Рассмотрим вторую функцию:

int g(n) {
  int x = 0;
  for (int k = 1 to 2) {
    for (int i = 1 to n) {
      for (int j = 1 to n) {
        ++x;
      }
    }
  }
  return x;
}

Внешний цикл работает дважды. Средний цикл работает n раз. Каждый раз, когда выполняется средний цикл, внутренний цикл выполняется n раз. Это устанавливает время работы при T (n) = 2n 2 .

Теперь вопрос в том, каково асимптотическое время выполнения обеих функций?

Чтобы рассчитать это, мы выполним два шага:

  • Удалить константы. Поскольку алгоритмы увеличиваются во времени за счет входных данных, другие термины доминируют во времени выполнения, что делает их неважными.
  • Удалить все, кроме самого большого срока. По мере того как n уходит в бесконечность, n 2 быстро опережает n .

Ключевым моментом здесь является фокус на доминирующих терминах и упрощение до этих терминов .

T (n) = n 2 ∈ ϴ (n 2 )
T (n) = 2n 2 ∈ ϴ (n 2 )

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

T (n) = 2n 2 + 4n + 7 ∈ ϴ (n 2 )

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

Расчет Big-Ω и Big-O

Во-первых, имейте в виду, что в неофициальной литературе «Big-O» часто рассматривается как синоним Big-Θ, возможно, потому, что греческие буквы сложно набрать. Так что, если кто-то неожиданно спросит вас о Big-O алгоритма, он, вероятно, захочет его Big-Θ.

Теперь, если вы действительно хотите вычислить Big-Ω и Big-O в формальных значениях, определенных ранее, у вас есть главная проблема: существует бесконечно много описаний Big-Ω и Big-O для любой данной функции! Это все равно, что спросить, какие числа меньше или равны 42. Есть много возможностей.

Для алгоритма с T (n) ∈ ϴ (n 2 ) любые из следующих формально допустимых утверждений:

  • T (n) ∈ O (n 2 )
  • T (n) ∈ O (n 3 )
  • T (n) ∈ O (n 5 )
  • T (n) ∈ O (n 12345 × e n )
  • T (n) ∈ Ω (n 2 )
  • T (n) ∈ Ω (n)
  • T (n) ∈ Ω (log (n))
  • T (n) ∈ Ω (log (log (n)))
  • T (n) ∈ Ω (1)

Но неверно утверждать, что T (n) ∈ O (n) или T (n) ∈ Ω (n 3 ) .

Что такое относительная сложность? Какие существуют классы алгоритмов?

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

Классы алгоритмов разбиваются следующим образом:

  • Θ (1) - постоянная. Например, выбор первого номера в списке всегда будет занимать одинаковое количество времени.

  • Θ (n) - линейный. Например, повторение списка всегда будет занимать время, пропорциональное размеру списка, n .

  • Θ (log (n)) - логарифмическая (база обычно не имеет значения). Алгоритмы, которые разделяют пространство ввода на каждом шаге, такие как бинарный поиск, являются примерами.

  • Θ (n × log (n)) - линейное время логарифмическое («линеарифмическое»). Эти алгоритмы обычно разделяют и побеждают ( log (n) ), в то же время повторяя ( n ) все входные данные. Многие популярные алгоритмы сортировки (сортировка слиянием, Timsort) попадают в эту категорию.

  • Θ (n m ) - многочлен ( n возведен в любую постоянную m ). Это очень распространенный класс сложности, часто встречающийся во вложенных циклах.

  • Θ (m n ) - экспоненциальный (любая константа m, возведенная в n ). Многие рекурсивные и графовые алгоритмы попадают в эту категорию.

  • Θ (n!) - факториал. Некоторые графовые и комбинаторные алгоритмы имеют факториальную сложность.

Это как-то связано с лучшим / средним / худшим случаем?

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

Чтобы говорить о Big-O алгоритма, нужно взять на вооружение конкретную математическую модель алгоритма с ровно одним параметром n, который должен описывать «размер» входных данных в каком бы то ни было смысле. Но в реальном мире входы имеют гораздо больше структуры, чем просто их длина. Если бы это был алгоритм сортировки, я мог бы питаться в строках "abcdef", "fedcba"или "dbafce". Все они имеют длину 6, но один из них уже отсортирован, один перевернут, а последний - просто случайный беспорядок. Некоторые алгоритмы сортировки (например, Timsort) работают лучше, если входные данные уже отсортированы. Но как включить эту неоднородность в математическую модель?

Типичный подход состоит в том, чтобы просто предположить, что входные данные поступают от некоторого случайного, вероятностного распределения Затем вы усредняете сложность алгоритма по всем входам с длиной n. Это дает вам модель сложности в среднем случае . Отсюда вы можете использовать обозначения Big-O / Θ / Ω как обычно, чтобы описать поведение среднего случая.

Но если вас беспокоят атаки типа «отказ в обслуживании», возможно, вам следует быть более пессимистичными. В этом случае безопаснее предположить, что единственными входными данными являются те, которые вызывают наибольшее количество горе в вашем алгоритме. Это дает вам модель сложности алгоритма в худшем случае . После этого вы можете говорить о Big-O / Θ / Ω и т. Д. Модели наихудшего случая .

Точно так же вы также можете сфокусировать свой интерес исключительно на входах, с которыми у вашего алгоритма меньше всего проблем, чтобы прийти к модели наилучшего случая , а затем взглянуть на Big-O / Θ / Ω и т. Д.


Это хороший ответ, но Big-O и Big-Ω имеют мало общего с худшими и лучшими случаями. Они представляют собой верхнюю и нижнюю границы, но оба они могут применяться к любому случаю, например, сортировка вставок имеет в лучшем случае временную сложность ϴ(n)(как Big-O, так и Big-Ω), в то время как в худшем случае временная сложность ϴ(n²)(как Big-O, так и Big-Ω).
Пол

Кроме того, любой алгоритм, за исключением пустого алгоритма, имеет Ω(1)место в лучшем, худшем и среднем случаях, но это потому, что он является нижней границей и не имеет ничего общего с фактическим лучшим случаем алгоритма.
Пол

Большое - все, что не имеет ничего общего с лучшим или худшим случаем - это распространенное заблуждение. Это просто способы указать, растет ли детерминистическая функция быстрее, медленнее или с той же скоростью по сравнению с другой. Понятие наилучшего / наихудшего случая существует только после того, как вы начинаете говорить о временной / пространственной сложности реальных алгоритмов, и в этом случае возникают недетерминированные факторы, и вам необходимо учитывать распределение вероятностей ваших входных данных. Даже тогда, лучший / худший случай лежит на оси, ортогональной к большому O / Omega.
Rufflewind

@Rufflewind, если ты думаешь, что можешь описать это лучше, тогда давай. Вы понимаете, что это ответ сообщества вики, верно?

«Прежде всего, имейте в виду, что в неформальной литературе« Big-O »часто трактуется как синоним Big-Θ» -> Не только в неформальной литературе. Мой первый семестр по сложности, еще в колледже, научил нас определению Big-O, как если бы оно было Big-Θ. (В нашем учебнике использовалось это определение!) Это чертовски смутило меня, когда я пошла на Сложность II, и обнаружила, что они не совпадают.
Т. Сар - Восстановить Монику
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.