Визначення, чи є алгоритм O (log n)


25

Я оновлюю свою теорію CS і хочу знати, як визначити складність алгоритму O (log n). Зокрема, чи існує простий спосіб її визначити?

Я знаю, що з O (n) у вас зазвичай є одна петля; O (n ^ 2) - подвійна петля; O (n ^ 3) - потрійна петля тощо. Як щодо O (log n)?


2
stackoverflow.com/questions/749819 / ... або це дійсно тривалий читати: stackoverflow.com/questions/487258 / ...
WKL

Ах, це одне місце, на яке я не дивився :)
Atif

Відповіді:


32

Я знаю, що з O (n) у вас зазвичай є одна петля; O (n ^ 2) - подвійна петля; O (n ^ 3) - потрійна петля тощо. Як щодо O (log n)?

Ти справді йдеш про це неправильним шляхом. Ви намагаєтеся запам’ятати, який вираз big-O йде з заданою алгоритмічною структурою, але вам слід просто підрахувати кількість операцій, необхідних алгоритму, і порівняти їх з розміром вводу. Алгоритм, який циклічно працює над усім входом, має O (n) продуктивність, тому що він працює циклі n разів, а не тому, що він має один цикл. Ось один цикл із виконанням O (log n):

for (i = 0; i < log2(input.count); i++) {
    doSomething(...);
}

Отже, будь-який алгоритм, де кількість необхідних операцій знаходиться на порядку логарифму розміру вхідного сигналу, є O (log n). Важливим, що говорить вам великий-O аналіз, - це те, як змінюється час виконання алгоритму щодо розміру вводу: якщо ви подвоїте розмір введення, чи робить алгоритм ще 1 крок (O (log n)) , вдвічі більше кроків (O (n)), у чотири рази більше кроків (O (n ^ 2)) тощо.

Чи допомагає з досвіду дізнатися, що алгоритми, які повторно розбивають свої вхідні дані, як правило, містять 'log n' як складову їхньої продуктивності? Звичайно. Але не шукайте розбиття і переходьте до висновку, що продуктивність алгоритму - O (log n) - це може бути щось на зразок O (n log n), що зовсім інше.


3
Зауважимо, що більш розмовний спосіб сказати «на порядок логарифму розміру» - сказати «на порядок кількості цифр у розмірі».

@Caleb фактична основа логарифму є неважливою, коли говорити про масштабування.

@Caleb говорити абсолюти не має сенсу з big-O. Формулювання, яке вам може подобатися краще: коли кількість цифр подвоюється, кількість кроків подвоюється.

@Caleb говорити абсолюти не має сенсу з big-O. Формулювання, яке вам може подобатися краще: коли кількість цифр подвоюється, кількість кроків подвоюється.

@ ThorbjørnRavnAndersen Так, саме це означає "логарифм розміру". Я не впевнений, у чому полягає ваша проблема з фразою, за винятком того, що ви вирішили сказати це інакше. В принципі, я думаю, що ми згодні.
Калеб

25

Ідея полягає в тому, що алгоритм полягає в тому, O(log n)якщо замість прокручування структури 1 на 1, ви розділите структуру навпіл і знову і зробите постійну кількість операцій для кожного розщеплення. Пошук алгоритмів, де простір відповідей продовжує ділитися O(log n). Прикладом цього є двійковий пошук , коли ви постійно ділите упорядкований масив навпіл і знову, поки не знайдете число.

Примітка. Не обов’язково розбиватися на рівні половинки.


1
Що робити, якщо я розділити вхід на два, а потім повторити 2 ^ (n / 2) рази на залишок, перш ніж розділити його знову? (Звичайно, я знаю, що тоді, я просто хотів показати приклад, коли цей спрощений підхід не вдається).
Tamás Szelei

@afish Це рідко. Це надзвичайно рідко при пошуку.
Стипендіати Дональ

1
@DonalFellows Алгоритм теорії не є емпіричною наукою. І питання полягало не в пошуку, це просто в тому, що згадка про log nспрацьовані бінарні рефлекси пошуку у людей.
Tamás Szelei

2
Розбиття не робить алгоритм O (log n), він (як правило) додає коефіцієнт log n до межі big-O. Рекурсивні сорти, такі як гипсорт і злиття, є ідеальними прикладами: вони розділяють вхід, але потім рекурсивно розподіляють обидві отримані розділи. Результатом є продуктивність O (n log n).
Калеб

@afish: Добре. Моя мета з цією відповіддю - зробити її максимально простою, враховуючи характер питання. Я змінив рядок "Ви поділите структуру навпіл ..." на "Ви поділите структуру навпіл ... і зробіть постійну кількість операцій для кожного розколу", щоб спробувати просто зрозуміти цю точку.
Кейсі Паттон

2

Типовими прикладами є приклади, які стосуються двійкового пошуку. Наприклад, зазвичай використовується двійковий алгоритм пошукуO(log n) .

Якщо у вас є двійкове дерево пошуку, пошук, вставлення та видалення є всіма O(log n)складними.

Будь-яка ситуація, коли ви постійно розділяєте простір, часто включає log nкомпонент. Ось чому багато алгоритмів сортування мають O(nlog n)складність, оскільки вони часто розбивають набір і сортують по ходу.


1

Якщо ви хочете, щоб це було так само просто, як "одиночний цикл -> O (n), подвійний цикл -> O (n ^ 2)", ніж відповідь, ймовірно, "Дерево -> O (журнал n)". Точніше обходити дерево від кореня до одного (не всього!) Листочка чи навпаки. Однак це все надмірні спрощення.


Отже, що не так з моєю відповіддю? Я відкритий для конструктивної критики.
шарфрідж

0

Ви хочете знати, чи існує простий спосіб визначити, чи є алгоритмом O (log N).

Ну: просто біжи і час. Запустити його для входів 1.000, 10.000, 100.000 і мільйон.

Якщо ви бачите час роботи 3,4,5,6 секунди (або кілька кратних), можете сміливо сказати, що це O (log N). Якщо він більше схожий на: 1 100001000 секунд, то, ймовірно, це O (N). І якщо це як 3,40,500,6000 секунд, то це O (N log N).


Кожна людина повинна дати цю відповідь по одній нагоді та по одній нижчій мові, обидві з очевидних причин :-)
gnasher729
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.