Что означает O (log n)?

Я узнаю о времени работы Big O Notation и времени амортизации. Я понимаю понятие O (n) линейного времени, означающего, что размер входных данных влияет на рост алгоритма пропорционально... и то же самое относится, например, к квадратичному времени O (n 2) и т.д. Даже к алгоритмам такие как генераторы перестановок, с O (n!) раз, которые растут на факториалах.

Например, следующая функция - O (n), потому что алгоритм растет пропорционально его входу n:

f(int n) {
  int i;
  for (i = 0; i < n; ++i)
    printf("%d", i);
}

Точно так же, если бы был вложенный цикл, время было бы O (n 2).

Но что именно O (log n)? Например, что значит сказать, что высота полного двоичного дерева равна O (log n)?

Я знаю (возможно, не очень подробно), что такое логарифм, в том смысле, что: log 10 100 = 2, но я не могу понять, как определить функцию с логарифмическим временем.

Ответ 1

Я не могу понять, как определить функцию со временем журнала.

Наиболее распространенные атрибуты логарифмической функции времени выполнения:

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

или же

  • элементы, над которыми выполняется действие, это цифры n

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

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


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

Вот время выполнения некоторых операций, которые мы могли бы выполнять в телефонной книге, от лучших к худшим:

  • O (1) (в лучшем случае): учитывая страницу с названием компании и названием компании, найдите номер телефона.

  • O (1) (средний регистр): учитывая страницу с именем человека и его именем, найдите номер телефона.

  • O (log n): По имени человека найдите номер телефона, выбрав случайную точку примерно на полпути в той части книги, которую вы еще не искали, а затем проверьте, находится ли имя человека в этой точке. Затем повторите процесс примерно на полпути через часть книги, где находится имя человека. (Это бинарный поиск по имени человека.)

  • O (n): Найти всех людей, номера телефонов которых содержат цифру "5".

  • O (n): По номеру телефона найдите человека или компанию с этим номером.

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

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

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

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

  • O (n · n!): Мы готовы загрузить телефонные книги в док-станцию. К сожалению, робот, который должен был загружать книги, стал бесполезным: он складывал книги в грузовик в случайном порядке! Хуже того, он загружает все книги в грузовик, а затем проверяет, находятся ли они в правильном порядке, а если нет, то выгружает их и начинает все сначала. (Это ужасный вид бого.)

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

Для более математического объяснения вы можете проверить, как сложность времени достигает log n здесь. https://hackernoon.com/what-does-the-time-complexity-o-log-n-actually-mean-45f94bb5bfbf

Ответ 2

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

Что значит сказать, что высота полного двоичного дерева равна O (log n)?

На следующем рисунке изображено двоичное дерево. Обратите внимание, как каждый уровень содержит удвоенное количество узлов по сравнению с уровнем выше (следовательно, двоичным):

Двоичное дерево

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

Предположим, у нас вместо этого был набор данных с 32 элементами. Продолжайте рисовать выше, чтобы найти, что нам теперь понадобятся 5 сравнений, чтобы найти то, что мы ищем, поскольку дерево только выросло на один уровень глубже, когда мы умножали объем данных. В результате сложность алгоритма может быть описана как логарифмический порядок.

Построение log(n) на простом листе бумаги приведет к графику, где рост кривой замедляется при n возрастает:

O (log n)

Ответ 3

O(log N) в основном означает, что время идет линейно, а n - экспоненциально. Поэтому, если для вычисления элементов 10 требуется 1 second, для вычисления элементов 100 требуется 2 секунд, 3 секунд), чтобы вычислить элементы 1000 и т.д.

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

Ответ 4

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

Двоичное дерево - это случай, когда проблема размера n делится на подзадачу размером n/2, пока мы не достигнем проблемы размера 1:

высота двоичного дерева

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

Общий алгоритм с временной сложностью O (log n) - это двоичный поиск, рекурсивным отношением которого является T (n/2) + O (1), то есть на каждом последующем уровне дерева вы делите проблему на половину и выполняете постоянное количество дополнительная работа.

Ответ 5

Обзор

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

Во-первых, вы захотите иметь общее представление о логарифме, которое вы можете получить из https://en.wikipedia.org/wiki/Logarithm. Естественные науки используют e и естественный журнал. Инженерные ученики будут использовать log_10 (база 10 базы данных), и компьютерные ученые будут использовать log_2 (база 2 базы) много, поскольку компьютеры основаны на двоичном коде. Иногда вы видите аббревиатуры естественного журнала как ln(), инженеры обычно оставляют _10 и просто используют log(), а log_2 сокращается как lg(). Все типы логарифмов растут аналогичным образом, поэтому они имеют одну и ту же категорию log(n).

Когда вы смотрите на примеры кода ниже, я рекомендую посмотреть на O (1), затем O (n), затем O (n ^ 2). После того, как вы добры с ними, посмотрите на других. Я включил чистые примеры, а также варианты, демонстрирующие, как тонкие изменения могут по-прежнему приводить к одной и той же категоризации.

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

введите описание изображения здесь

Простые примеры кода из разных больших категорий O:

O (1) - Примеры с постоянным временем:

  • Алгоритм 1:

Алгоритм 1 печатает привет однократно, и он не зависит от n, поэтому он всегда будет работать в постоянное время, поэтому он O(1).

print "hello";
  • Алгоритм 2:

Алгоритм 2 печатает привет 3 раза, однако он не зависит от размера ввода. Даже когда n растет, этот алгоритм всегда будет печатать только 3 раза. То, что сказано 3, является константой, поэтому этот алгоритм также O(1).

print "hello";
print "hello";
print "hello";

O (log (n)) - Логарифмические примеры:

  • Алгоритм 3 - это действует как "log_2"

Алгоритм 3 демонстрирует алгоритм, который работает в log_2 (n). Обратите внимание, что пост-операция цикла for умножает текущее значение я на 2, поэтому i переходит от 1 до 2 к 4 к 8 к 16 к 32...

for(int i = 1; i <= n; i = i * 2)
  print "hello";
  • Алгоритм 4 - Это действует как "log_3"

Алгоритм 4 демонстрирует log_3. Уведомление i идет от 1 до 3 до 9 до 27...

for(int i = 1; i <= n; i = i * 3)
  print "hello";
  • Алгоритм 5 - Это действует как "log_1.02"

Алгоритм 5 важен, так как он помогает показать, что, пока число больше 1, и результат многократно умножается на себя, вы смотрите на логарифмический алгоритм.

for(double i = 1; i < n; i = i * 1.02)
  print "hello";

O (n) - Примеры линейного времени:

  • Алгоритм 6

Этот алгоритм прост, который печатает привет n раз.

for(int i = 0; i < n; i++)
  print "hello";
  • Алгоритм 7

Этот алгоритм показывает вариацию, где он будет печатать hello n/2 раза. n/2 = 1/2 * n. Мы игнорируем константу 1/2 и видим, что этот алгоритм O (n).

for(int i = 0; i < n; i = i + 2)
  print "hello";

O (n * log (n)) - nlog (n) Примеры:

  • Алгоритм 8

Подумайте об этом как о комбинации O(log(n)) и O(n). Вложенность циклов for помогает нам получить O(n*log(n))

for(int i = 0; i < n; i++)
  for(int j = 1; j < n; j = j * 2)
    print "hello";
  • Алгоритм 9

Алгоритм 9 подобен алгоритму 8, но каждый из циклов допускает изменения, которые по-прежнему приводят к тому, что конечный результат равен O(n*log(n))

for(int i = 0; i < n; i = i + 2)
  for(int j = 1; j < n; j = j * 3)
    print "hello";

O (n ^ 2) - n квадрат Примеры:

  • Алгоритм 10

O(n^2) получается легко путем вложения стандарта для циклов.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j++)
    print "hello";
  • Алгоритм 11

Как и алгоритм 10, но с некоторыми вариантами.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j = j + 2)
    print "hello";

O (n ^ 3) - n cubed Примеры:

  • Алгоритм 12

Это похоже на алгоритм 10, но с 3 циклами вместо 2.

for(int i = 0; i < n; i++)
  for(int j = 0; j < n; j++)
    for(int k = 0; k < n; k++)
      print "hello";
  • Алгоритм 13

Как и алгоритм 12, но с некоторыми вариациями, которые все еще дают O(n^3).

for(int i = 0; i < n; i++)
  for(int j = 0; j < n + 5; j = j + 2)
    for(int k = 0; k < n; k = k + 3)
      print "hello";

Резюме

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

Ответ 6

Если у вас есть функция, которая принимает:

1 millisecond to complete if you have 2 elements.
2 milliseconds to complete if you have 4 elements.
3 milliseconds to complete if you have 8 elements.
4 milliseconds to complete if you have 16 elements.
...
n milliseconds to complete if you have 2**n elements.

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

Ответ 7

Логарифмическое время работы (O(log n)) по существу означает, что время работы растет пропорционально логарифму входного размера - в качестве примера, если 10 элементов занимают не более некоторого времени x, а 100 единиц самое большее, скажем, 2x, а 10 000 элементов занимают не более 4x, тогда это выглядит как сложность времени O(log n).

Ответ 8

Логарифм

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

Представьте, что у нас есть веревка, и мы привязали ее к лошади. Если веревка непосредственно привязана к лошади, сила, которую лошадь должна оттянуть (скажем, от человека), будет прямо 1.

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

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

введите описание изображения здесь

Мы можем видеть, что для каждого цикла значение увеличивается на 10. Количество поворотов, необходимых для получения любого числа, называется логарифмом числа, т.е. нам нужно 3 сообщения до нескольких ваших сил в 1000 раз, 6 сообщений для умножения ваша сила на 1 000 000.

3 - логарифм 1000, а 6 - логарифм 1 000 000 (основание 10).

То, что на самом деле означает O (log n)?

В нашем примере выше наш "темп роста" O (log n). Для каждого дополнительного цикла сила, которую может использовать наша веревка, в 10 раз больше:

Turns | Max Force
  0   |   1
  1   |   10
  2   |   100
  3   |   1000
  4   |   10000
  n   |   10^n

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

Теперь представьте, что вы пытаетесь угадать число между 1-100.

Your Friend: Guess my number between 1-100! 
Your Guess: 50
Your Friend: Lower!
Your Guess: 25
Your Friend: Lower!
Your Guess: 13
Your Friend: Higher!
Your Guess: 19
Your Friend: Higher!
Your Friend: 22
Your Guess: Lower!
Your Guess: 20
Your Friend: Higher!
Your Guess: 21
Your Friend: YOU GOT IT!  

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

Guesses | Items
  1     |   2
  2     |   4
  3     |   8
  4     |   16
  5     |   32
  6     |   64
  7     |   128
  10    |   1024

Используя график, мы можем видеть, что если мы используем бинарный поиск для угадывания числа между 1-100, это потребует не более 7 попыток. Если бы у нас было 128 чисел, мы могли бы также угадать число в 7 attemps, но 129 чисел будут принимать не более 8 попыток (в отношении к логарифмам здесь нам понадобятся 7 догадок для диапазона значений 128, 10 догадок для диапазона значений 1024. 7 - это логарифм 128, 10 - логарифм 1024 (основание 2)).

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

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

Как насчет O (n log n)?

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

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

Отказ от ответственности: пример веревочного логарифма был схвачен за отличную книгу Mathematician Delight от W.Sawyer.

Ответ 9

Вы можете думать об O (log N) интуитивно, говоря, что время пропорционально количеству цифр в N.

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

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

И так далее.

Ответ 10

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

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

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

Ответ 11

Какой журнал b (n)?

Это количество раз, когда вы можете вырезать журнал длины n несколько раз в b равных частей, прежде чем достигнуть раздела размером 1.

Ответ 12

Сначала я рекомендую вам прочитать следующую книгу;

Алгоритмы (4-е издание)

Вот некоторые функции и их ожидаемые сложности. Числа указывают частоты выполнения операторов.

Here is some functions and their expected complexities

Схема сложностей Big-O также взята из таблицы Bigocheats Big-O Complexity Chart

Наконец, очень простая витрина показывает, как она рассчитывается;

Анатомия частот выполнения операторов программ.

Анализ времени выполнения программы (пример).

Analyzing the running time of a program

Ответ 13

В алгоритмах разделения и покорения обычно есть компонент logn для времени выполнения. Это происходит из-за повторной половины входа.

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

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

Ответ 14

Но что такое O (log n)? Например, что означает сказать, что высота полного бинарного дерева равна O (log n)?

Я бы перефразировал это как "высота полного двоичного дерева - log n". При определении высоты полного двоичного дерева должно быть O (log n), если вы проходили шаг за шагом.

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

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

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

Ответ 15

Эти 2 случая будут принимать время O (log n)

case 1: f(int n) {
      int i;
      for (i = 1; i < n; i=i*2)
        printf("%d", i);
    }


 case 2  : f(int n) {
      int i;
      for (i = n; i>=1 ; i=i/2)
        printf("%d", i);
    }

Ответ 16

O (log n) немного вводит в заблуждение, точнее это O (log 2 n), т.е. (логарифм с базой 2).

Высота сбалансированного двоичного дерева равна O (log 2 n), так как каждый node имеет два (обратите внимание на "два", как в log 2 n ) дочерние узлы. Таким образом, дерево с n узлами имеет высоту log 2 n.

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

Ответ 17

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

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

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

Сложность времени выполнения двоичного поиска является примером O(log n). Это связано с тем, что в двоичном поиске вы всегда игнорируете половину вашего ввода на каждом последующем этапе, разделив массив пополам и сосредоточившись на одной половине с каждым шагом. Каждый шаг является постоянным, потому что в бинарном поиске вам нужно только сравнить один элемент с вашим ключом, чтобы выяснить, что делать дальше независимо от того, насколько большой массив, который вы рассматриваете, в любой момент. Таким образом, вы выполняете приблизительно log (n)/log (2) шаги.

Сложность времени выполнения сортировки слияния является примером O(n log n). Это связано с тем, что вы разделяете массив пополам с каждым шагом, в результате чего в общей сложности выполняются шаги log (n)/log (2). Тем не менее, на каждом шаге вам необходимо выполнить операции слияния для всех элементов (будь то операция слияния двух подписок из n/2 элементов или двух операций слияния в четырех подкристах из n/4 элементов, не имеет значения, поскольку она добавляет к необходимости сделайте это для n элементов на каждом шаге). Таким образом, общая сложность O(n log n).

* Помните, что обозначение big-O, по определению, константы не имеют значения. Также с помощью изменения базового правила для логарифмов единственное различие между логарифмами разных баз является постоянным фактором.

Ответ 18

Это просто означает, что время, необходимое для этой задачи, растет с помощью log (n) (пример: 2s для n = 10, 4s для n = 100,...). Прочтите статьи Википедии о Алгоритм двоичного поиска и Значения Big O для большего количества исправлений.

Ответ 19

Проще говоря: На каждом шаге вашего алгоритма вы можете сократить работу пополам. (Асимптотически эквивалентно третьему, четвертому,...)

Ответ 20

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

Поэтому алгоритмы с логарифмической временной сложностью пользуются большим спросом: даже для действительно больших n (например, n = 10 ^ 8) они выполняют более чем приемлемо.

Ответ 21

Но что такое O (log n)

То, что это означает, точно: "поскольку n стремится к infinity, time стремится к a*log(n), где a - постоянный масштабный коэффициент".

Или, на самом деле, это не совсем значит; скорее это означает, что что-то вроде "time, деленное на a*log(n), стремится к 1".

"Тенденции к" имеет обычный математический смысл из "анализа": например, "если вы выберете любую произвольно малую ненулевую константу k, то я могу найти соответствующее значение X такое, что ((time/(a*log(n))) - 1) меньше k для всех значений n больше X."


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

Обратите внимание, что если бы уравнение было, например...

время (n) = a + blog (n) + cn + dnn

... тогда это будет O (n квадрат), потому что, независимо от значений констант a, b, c и ненулевых d, член d*n*n всегда будет доминировать над другими для любого достаточно большое значение n.

То, что означает обозначение бит O: это означает "какой порядок доминирующего члена для любого достаточно большого n".

Ответ 22

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

Теперь, если вы можете доказать, что на каждой итерации вашего алгоритма вы отрезаете часть этого пространства, то есть не меньше определенного предела, это означает, что ваш алгоритм работает в O (logN).

Я должен указать, что мы говорим здесь об относительном пределе фракции, а не о абсолютном. Бинарный поиск является классическим примером. На каждом шаге мы выбрасываем 1/2 проблемного пространства. Но двоичный поиск - не единственный такой пример. Предположим, вы как-то доказали, что на каждом шаге вы выбрасываете по крайней мере 1/128 проблемного пространства. Это означает, что ваша программа все еще работает в режиме O (logN), хотя значительно медленнее, чем двоичный поиск. Это очень хороший намек на анализ рекурсивных алгоритмов. Часто можно доказать, что на каждом этапе рекурсия не будет использовать несколько вариантов, и это приведет к отсечению некоторой доли в проблемном пространстве.

Ответ 23

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

Это означает, что в цикле шаг растет экспоненциально. Например.

for (i=1; i<=n; i=i*2) {;}

Сложность в O-нотации этой программы O (log (n)). Попробуйте пропустить его вручную (n находится где-то между 512 и 1023 (исключая 1024):

step: 1   2   3   4   5    6    7    8     9     10
   i: 1   2   4   8   16   32   64   128   256   512

Хотя n находится где-то между 512 и 1023, происходит только 10 итераций. Это связано с тем, что шаг в цикле растет экспоненциально и, следовательно, для завершения термина требуется только 10 итераций.

Логарифм x (на основании a) является обратной функцией a ^ x.

Это похоже на то, что логарифм является инверсией экспоненты.

Теперь попробуйте это посмотреть, если экспоненциальная скорость растет очень быстро, то логарифм растет (обратно) очень медленно.

Разность между O (n) и O (log (n)) огромна, подобно разности между O (n) и O (a ^ n) (a - константа).

Ответ 24

Tree

log x to base b = y является обратным к b^y = x

Если у вас есть M-арное дерево глубины d и размер n, то:

  • проходящее по всему дереву ~ O (M ^ d) = O (n)

  • Прохождение одиночного пути в дереве ~ O (d) = O (log n до базы M)

Ответ 25

В информационной технологии это означает, что:

  f(n)=O(g(n)) If there is suitable constant C and N0 independent on N, 
  such that
  for all N>N0  "C*g(n) > f(n) > 0" is true.

Ant кажется, что эти обозначения были в основном взяты из математики.

В этой статье есть цитата: D.E. Кнут, "БОЛЬШОЙ ОМИКРОН И БОЛЬШАЯ ОМЕГА И БОЛЬШАЯ ТЕТА" , 1976 г.:

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

Сегодня 2016 год, но мы используем его еще сегодня.


В математическом анализе это означает, что:

  lim (f(n)/g(n))=Constant; where n goes to +infinity

Но даже в математическом анализе иногда этот символ использовался в значении "C * g (n) > f (n) > 0".

Как я знаю из университета, этот символ был изобретен немецким математиком Ландау (1877-1938)

Ответ 26

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

На первом этапе вы делите на 2. Затем у вас есть 2 списка (2 ^ 1), вы разделите их на 2, так что у вас есть 4 списка (2 ^ 2), вы снова разделите, у вас есть 8 списков ( 2 ^ 3) и так далее, пока ваш размер списка не станет 1

Это дает вам уравнение:

n/(2^steps)=1 <=> n=2^steps <=> lg(n)=steps

(вы берете lg каждой стороны, lg являетесь базой 2)

Ответ 27

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

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

Поскольку временная сложность зависит от различных параметров, а именно:
1. Физическая система
2. Язык программирования
3. Стиль кодирования
4. И многое другое......

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


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

Ниже приведен пример алгоритма линейного времени


Линейный поиск
Учитывая n элементов ввода, для поиска элемента в массиве вам нужно не более 'n' сравнений. Другими словами, независимо от того, какой язык программирования вы используете, какой стиль кодирования вы предпочитаете, в какой системе вы его выполняете. В худшем случае это требует только n сравнений. Время выполнения линейно пропорционально размеру ввода.

И это не просто поиск, какова бы ни была работа (приращение, сравнение или любая операция), ее функция размера ввода.

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

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

      n      Work
      2     1 units of work
      4     2 units of work
      8     3 units of work

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

Ответ 28

Если вы ищете ответ на основе интуиции, я хотел бы рассказать вам две интерпретации.

  • Представьте себе очень высокий холм с очень широкой базой. Чтобы добраться до вершины холма, есть два пути: один - выделенный путь, идущий по спирали по холму, достигающий вершины, а другой: небольшая терраса, подобная резьбе, вырезанной для обеспечения лестницы. Теперь, если первый путь достигает линейного времени O (n), второй - O (log n).

  • Представьте себе алгоритм, который принимает целое число n как входное и завершает во времени пропорционально n, тогда это O (n) или theta (n), но если он работает во времени пропорционально number of digits or the number of bits in the binary representation on number, тогда алгоритм выполняется в O (log n) или theta (log n) времени.

Ответ 29

Полный двоичный пример - O (ln n), потому что поиск выглядит следующим образом:

1 2 3 4 5 6 7 8 9 10 11 12

Поиск 4 уроков 3 удара: 6, 3, затем 4. И log2 12 = 3, что является хорошим показателем того, сколько хитов там, где это необходимо.

Ответ 30

Алгоритмы в парадигме Divide и Conquer имеют сложность O (logn). Например, вычислите свою собственную функцию мощности,

int power(int x, unsigned int y)
{
    int temp;
    if( y == 0)
        return 1;
    temp = power(x, y/2);
    if (y%2 == 0)
        return temp*temp;
    else
        return x*temp*temp;
}

из http://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/