як обчислити двійкову складність пошуку


144

Я чув, як хтось говорить, що оскільки двійковий пошук наполовину вводить необхідний для пошуку, то це алгоритм log (n). Оскільки я не з математичного походження, я не в змозі з цим ставитися. Чи може хтось пояснити це трохи детальніше? чи має щось робити з логарифмічним рядом?


1
це може допомогти вам: stackoverflow.com/a/13093274/550393
2cupsOfTech

Відповіді:


385

Ось більш математичний спосіб його бачити, хоча і не дуже складно. ІМО набагато зрозуміліші, як неформальні:

Питання в тому, скільки разів ви можете розділити N на 2, поки у вас немає 1? Це, по суті, говорить, виконайте двійковий пошук (половина елементів), поки ви його не знайшли. У формулі це було б таке:

1 = N / 2 x

помножити на 2 х :

2 х = N

тепер зробіть журнал 2 :

log 2 (2 x ) = log 2 N
x * log 2 (2) = log 2 N
x * 1 = log 2 N

це означає, що ви можете розділити журнал N разів, поки ви не розділите все. Що означає, що вам потрібно розділити журнал N ("зробіть крок бінарного пошуку"), поки ви не знайдете свій елемент.


я щойно обчислив його до t (n) = (2 ^ 2) * K. як зробити так, щоб увійти до форми?
Шань Хан

1
те ж саме поняття пояснив графічно: stackoverflow.com/a/13093274/550393
2cupsOfTech

Частина, яку мені не вистачає, якщо у вас є BST з 7 записами, яка його формула? log2 (7)? Я робив підрахунок грубої сили з кожним можливим результатом і дійшов відповіді, що не дорівнює log2 (7), так що я роблю неправильно?
Перрі Моншау

1
Так набагато простіше, ніж пояснення бінарного дерева.
NoName

1
Дуже приємна відповідь
VHS

22

Для двійкового пошуку T (N) = T (N / 2) + O (1) // відношення рецидиву

Застосуйте теорему магістра для обчислення складності часу відношення періодичності виконання: T (N) = aT (N / b) + f (N)

Тут a = 1, b = 2 => log (база b) = 1

також, тут f (N) = n ^ c log ^ k (n) // k = 0 & c = log (база b)

Отже, T (N) = O (N ^ c log ^ (k + 1) N) = O (log (N))

Джерело: http://en.wikipedia.org/wiki/Master_theorem


1
чому журнал (база b) дорівнює 1, коли a = 1 і b = 2, не повинен бути 0?
GAURANG VYAS

16

T (n) = T (n / 2) +1

T (n / 2) = T (n / 4) + 1 + 1

Поставте значення значення (n / 2) вище, щоб T (n) = T (n / 4) + 1 + 1. . . . T (n / 2 ^ k) + 1 + 1 + 1 ..... + 1

= T (2 ^ k / 2 ^ k) + 1 + 1 .... + 1 до k

= T (1) + k

Як ми взяли 2 ^ k = n

K = log n

Отже, складність у часі становить O (log n)


10

Це не половина часу пошуку, це не зробить його журнал (n). Він зменшує його логарифмічно. Подумайте про це на мить. Якщо у вас було 128 записів у таблиці і вам довелося шукати лінійно лінійно ваші значення, можливо, в середньому знадобиться близько 64 записів, щоб знайти ваше значення. Це n / 2 або лінійний час. За допомогою двійкового пошуку ви виключаєте 1/2 можливих записів кожної ітерації, так що для знаходження вашого значення знадобиться не більше 7 порівнянь (база журналу 2 із 128 - це 7, а потужність 7 - 128). Це сила двійкового пошуку.


Вибачте за некропост, але 128 не є рівномірно заповненим деревом. Я використав основний приклад, щоб обернутись цим шляхом, і я виявив, що 7 записів рівномірно заповнюють дерево в 3 шари. Я підрахував, що складність повинна становити 17/7 (середнє значення суми порівнянь), що становить 2,43. Але log2 (7) дорівнює 2,81. То чого мені тут не вистачає?
Перрі Моншау

Два відповіді - Перший тут: Навіть якщо в математиці немає помилок, ми можемо побачити, що 2,43 середнього значення все ж краще, ніж 3,5 середнього для лінійного, і це за низьким значенням. Після потрапляння в 100 записів, log2 () набагато краще, ніж лінійний. Я думаю, ви це бачите, тому далі.
Майкл Дорган

1
Друга відповідь: я не впевнений, яке дерево у вас там, де 7 все заповнило. Коли я думаю про ідеальне дерево з 8 записів, я бачу 3-рівневе глибоке дерево з 8 загальним листям. У цьому дереві, незалежно від того, яке число ви шукаєте, потрібно три загальних порівняння, щоб дістатися від кореня до листя. Для 7 записів один із контурів міг би порівняти менше, тому 20/7 (6 вузлів з 3 порівнянь, 1 вузол з 2 порівнянь), що становить ~ 2,85. Log2 (7) становить ~ 2,81. Я не маю передумови математики, щоб пояснити різницю .04, але, мабуть, це стосується того, щоб не було доступних дробових бітів чи якоїсь іншої магії :)
Michael Dorgan

число - це кількість листя !? Не кількість вузлів? Ну, це була велика інформація, яку мені не вистачало. Мені здається дивним, що функція заснована на листках, коли кожен вузол розгалуження також є потенційною зупинкою. Ну все одно, дякую, що випрямили це для мене!
Перрі Моншау

5

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

Це просто формальний математичний мов для того, щоб можна було доводити твердження тощо. Це має дуже відверте пояснення. Коли n зростає дуже великим, функція log n зростатиме час, необхідний для виконання функції. Розмір "вхідного набору", n, - це лише довжина списку.

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

Якщо чому це O (log n), а не O (log2 n), це тому, що просто поставте знову - Використання великих констант нотації O не рахується.


4

Ось запис у Вікіпедії

Якщо дивитися на простий ітеративний підхід. Ви просто усуваєте половину елементів, які потрібно шукати, поки не знайдете потрібний елемент.

Ось пояснення того, як ми придумали формулу.

Скажіть, що спочатку у вас є N кількість елементів, а тоді, що ви робите, це ⌊N / 2⌋ як перша спроба. Де N - сума нижньої межі та верхньої межі. Перше часове значення N було б рівним (L + H), де L - перший індекс (0), а H - останній індекс списку, який ви шукаєте. Якщо вам пощастить, елемент, який ви намагаєтесь знайти, буде посередині [напр. Ви шукаєте 18 у списку {16, 17, 18, 19, 20}, тоді ви обчислюєте ⌊ (0 + 4) / 2⌋ = 2, де 0 нижня межа (L - індекс першого елемента масиву) і 4 - вища межа (H ​​- індекс останнього елемента масиву). У наведеному вище випадку L = 0 і H = 4. Тепер 2 - це індекс елемента 18, який ви шукаєте. Бінго! Ви його знайшли.

Якби справа була іншим масивом {15,16,17,18,19}, але ви все ще шукали 18, то вам не пощастило б, і ви зробили б перший N / 2 (що становить ⌊ (0 + 4) / 2⌋ = 2, а потім реалізувати елемент 17 в індексі 2. - це не число, яке ви шукаєте. Тепер ви знаєте, що вам не потрібно шукати принаймні половину масиву при наступній спробі пошуку ітераційним способом. зусилля пошуку вдвічі зменшуються, тому в основному ви не шукаєте половини списку елементів, які ви шукали раніше, кожного разу, намагаючись знайти той елемент, який ви не змогли знайти в попередній спробі.

Тож найгірший випадок був би

[N] / 2 + [(N / 2)] / 2 + [((N / 2) / 2)] / 2 .....
тобто:
N / 2 1 + N / 2 2 + N / 2 3 + ..... + N / 2 x … ..

поки… ви не закінчили пошук, де в елементі, який ви намагаєтеся знайти, знаходиться в кінці списку.

Це показує найгірший випадок, коли ви досягаєте N / 2 x, де x таке, що 2 x = N

В інших випадках N / 2 x, де x таке, що 2 x <N Мінімальне значення x може бути 1, що є найкращим випадком.

Тепер, оскільки математично найгірший випадок - це значення
2 x = N
=> log 2 (2 x ) = log 2 (N)
=> x * log 2 (2) = log 2 (N)
=> x * 1 = log 2 (N)
=> Більш офіційно ⌊log 2 (N) + 1⌋


1
Як саме ви отримуєте більш офіційну версію?
Калле

Використовується функція підлоги. Деталі розміщені у розділі про ефективність посилання на wiki ( en.wikipedia.org/wiki/Binary_search_algorithm ), що міститься у відповіді.
RajKon


2

Скажімо, ітерація в двійковому пошуку закінчується після k ітерацій. При кожній ітерації масив ділиться навпіл. Отже, скажімо, що довжина масиву при будь-якій ітерації дорівнює n На Ітерації 1,

Length of array = n

Під час Ітерації 2

Length of array = n⁄2

Під час Ітерації 3

Length of array = (n⁄2)⁄2 = n⁄22

Тому після Ітерації k

Length of array = n⁄2k

Також ми знаємо, що після поділу After k довжина масиву стає 1 Отже

Length of array = n⁄2k = 1
=> n = 2k

Застосування функції журналу з обох сторін:

=> log2 (n) = log2 (2k)
=> log2 (n) = k log2 (2)
As (loga (a) = 1)

Тому

As (loga (a) = 1)
k = log2 (n)

Звідси складна часова складність Бінарного пошуку

log2 (n)

1

Двійковий пошук працює, поділяючи проблему навпіл повторно, щось подібне (деталі пропущені):

Приклад шукає 3 у [4,1,3,8,5]

  1. Замовте свій список предметів [1,3,4,5,8]
  2. Подивіться на середній пункт (4),
    • Якщо це те, що ви шукаєте, зупиніться
    • Якщо вона більша, подивіться на першу половину
    • Якщо менше, подивіться на другу половину
  3. Повторіть крок 2 з новим списком [1, 3], знайдіть 3 та зупиніться

Це дворічний пошук, коли поділиш проблему на 2.

Для пошуку потрібні лише кроки log2 (n), щоб знайти правильне значення.

Я рекомендую вступ до алгоритмів, якщо ви хочете дізнатися про алгоритмічну складність.


1

Оскільки ми скорочуємо список вдвічі, тому нам просто потрібно знати, скільки кроків ми отримуємо 1, коли ми ділимося списком на два. У наведеному нижче обчисленні х позначається кількість часу, який ми ділимо на список, поки не отримаємо один елемент (У гіршому випадку).

1 = N / 2x

2x = N

Беручи log2

log2 (2x) = log2 (N)

x * log2 (2) = log2 (N)

x = log2 (N)


1

T (N) = T (N / 2) + 1

T (N) = T (N / 2) + 1 = (T (N / 4) + 1) + 1

...

T (N) = T (N / N) + (1 + 1 + 1 + ... + 1) = 1 + logN (база 2 журналу) = 1 + logN

Отже, складність у часі двійкового пошуку становить O (logN)


0
ok see this
for(i=0;i<n;n=n/2)
{
i++;
}
1. Suppose at i=k the loop terminate. i.e. the loop execute k times.

2. at each iteration n is divided by half.

2.a n=n/2                   .... AT I=1
2.b n=(n/2)/2=n/(2^2)
2.c n=((n/2)/2)/2=n/(2^3)....... aT I=3
2.d n=(((n/2)/2)/2)/2=n/(2^4)

So at i=k , n=1 which is obtain by dividing n  2^k times
n=2^k
1=n/2^k 
k=log(N)  //base 2

0

Дозвольте мені полегшити всім вам приклад.

Для простоти припустимо, що в масиві впорядкованому порядку є 32 елементи, з яких ми шукаємо елемент за допомогою двійкового пошуку.

1 2 3 4 5 6 ... 32

Припустимо, що ми шукаємо 32. Після першої ітерації ми залишимося

17 18 19 20 .... 32

після другої ітерації ми залишимося

25 26 27 28 .... 32

після третьої ітерації ми залишимося

29 30 31 32

після четвертої ітерації ми залишимося

31 32

У п'ятій ітерації ми знайдемо значення 32.

Отже, якщо ми перетворимо це в математичне рівняння, отримаємо

(32 X (1/2 5 )) = 1

=> n X (2 -k ) = 1

=> (2 к ) = n

=> k log 2 2 = log 2 n

=> k = log 2 n

Звідси доказ.


0

Ось рішення з використанням основної теореми з читабельним LaTeX.

Для кожного рецидиву у відношенні рецидиву для двійкового пошуку ми перетворюємо задачу в одну підпроблему з виконуваним часом T (N / 2). Тому:

T (n) = T (n / 2) +1

Підставляючи головну теорему, отримуємо:

T (n) = aT (n / b) + f (n)

Тепер, оскільки логба0 і f (n) дорівнює 1, ми можемо використовувати другий випадок основної теореми, оскільки:

f (n) = O (1) = O (n0) = O (nlogba)

Це означає що:

T (n) = O (nlogbalogn) = O (n0logn) = O (logn)

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