Це раніше питання стосується деяких факторів, які можуть спричинити складність алгоритму O (log n).
Що спричинило б алгоритм складності часу O (журнал журналу n)?
Це раніше питання стосується деяких факторів, які можуть спричинити складність алгоритму O (log n).
Що спричинило б алгоритм складності часу O (журнал журналу n)?
Відповіді:
O (журнал n журналу n) терміни можуть відображатися в різних місцях, але зазвичай є два основні маршрути, які прибуватимуть у цей час виконання.
Як було сказано у відповіді на пов'язане запитання, загальним способом алгоритму мати складність у часі O (log n), щоб алгоритм працював, повторно скорочуючи розмір вхідного сигналу на деякий постійний коефіцієнт на кожній ітерації. Якщо це так, алгоритм повинен припинитися після ітерацій O (log n), оскільки після виконання поділів O (log n) постійною, алгоритм повинен зменшити розмір проблеми до 0 або 1. Ось чому, наприклад, , двійковий пошук має складність O (log n).
Цікаво, що існує аналогічний спосіб зменшення розміру проблеми, що дає час виконання форми O (log log n). Замість того, щоб ділити вхід навпіл на кожному шарі, що станеться, якщо взяти квадратний корінь розміру на кожному шарі?
Наприклад, візьмемо число 65,536. Скільки разів нам доводиться ділити це на 2, поки ми не опустимось на 1? Якщо ми це зробимо, отримаємо
Цей процес займає 16 кроків, а також 65 656 = 2 16 .
Але, якщо взяти квадратний корінь на кожному рівні, ми отримаємо
Зауважте, що потрібно лише чотири кроки, щоб досягти всього рівня 2. Чому це?
По-перше, інтуїтивне пояснення. Скільки цифр у числах n та √n? У номері n є приблизно log n цифр і приблизно log (√n) = log (n 1/2) ) = (1/2) log n цифр у √n. Це означає, що щоразу, коли ви берете квадратний корінь, ви приблизно вдвічі зменшуєте кількість цифр у кількості. Оскільки ви можете лише вдвічі зменшити кількість k O (log k), перш ніж вона знизиться до постійної (скажімо, 2), це означає, що ви можете приймати лише квадратні корені O (log n) разів, перш ніж зменшити кількість вниз до деякої постійної (скажімо, 2).
Тепер давайте зробимо трохи математики, щоб зробити це суворим. Давайте перепишемо вищезазначену послідовність з точки зору повноважень двох:
Зауважте, що ми дотримувались послідовності 2 16 → 2 8 → 2 4 → 2 2 → 2 1 . На кожній ітерації розрізаємо показник сили двох навпіл. Це цікаво, адже це пов'язане з тим, що ми вже знаємо, - ви можете розділити число k лише на половину O (log k), перш ніж воно впаде до нуля.
Тому візьміть будь-яке число n і запишіть його як n = 2 k . Кожен раз, коли ви берете квадратний корінь n, ви вдвічі збільшуєте показник у цьому рівнянні. Тому можуть бути лише O (log k) квадратні корінці, застосовані до того, як k падає на 1 або нижче (у цьому випадку n крапель до 2 або нижчих). Оскільки n = 2 k , це означає, що k = log 2 n, і тому число взятих квадратних коренів дорівнює O (log k) = O (log log n). Отже, якщо існує алгоритм, який працює за рахунок неодноразового зменшення задачі до підпрограми розміру, яка є квадратним коренем початкового розміру проблеми, цей алгоритм припиняється після кроків O (log n).
Одним із реальних прикладів цього є дерево ван Емде Боаса(vEB-дерево) структура даних. Дерево vEB - це спеціалізована структура даних для зберігання цілих чисел у діапазоні 0 ... N - 1. Вона працює таким чином: кореневий вузол дерева має у ньому вказівники √N, розбиваючи діапазон 0 ... N - 1 у bu відра, кожне з яких містить діапазон приблизно √N цілих чисел. Потім ці відра підрозділяються на ckets (√ N) відра, кожне з яких містить приблизно √ (√ N) елементів. Щоб обрізати дерево, ви починаєте з кореня, визначаєте, до якого відра належите, а потім рекурсивно продовжуєте у відповідному піддереві. Завдяки тому, як структуровано дерево vEB, ви можете за О (1) визначити час, в яке підгрупу слід спуститися, і тому після кроків O (журналу N) ви досягнете дна дерева. Відповідно, пошук у дереві vEB потребує часу лише O (журнал журналу N).
Інший приклад - алгоритм найближчої пари точок Hopcroft-Fortune . Цей алгоритм намагається знайти дві найближчі точки в колекції 2D балів. Це працює, створюючи сітку відра і розподіляючи точки в ці відра. Якщо в будь-якій точці алгоритму знайдено відро, яке має в ньому більше √N точок, алгоритм рекурсивно обробляє це відро. Отже, максимальна глибина рекурсії становить O (журнал журналу n), і за допомогою аналізу дерева рекурсії можна показати, що кожен шар у дереві працює O (n). Тому загальний час виконання алгоритму дорівнює O (n log log n).
Існують деякі інші алгоритми, які досягають часу виконання O (log n), використовуючи такі алгоритми, як двійковий пошук на об'єктах розміру O (log n). Наприклад, структура даних x-fast trie виконує двійковий пошук по шарах на дереві висоти O (log U), тому час виконання деяких операцій становить O (log log U). Пов'язане y-швидко трие отримує деякі свої O-режими виконання (log log U), підтримуючи врівноважені BSTs вузлів O (log U) кожен, дозволяючи пошукам у цих деревах запускатись у часі O (log log U). Дерево танго і родинні multisplay дерева структури даних , в кінцевому підсумку з O (журнал журнал п) в перспективі їх аналізу , оскільки вони зберігають дерева , які містять O (журнал п) елементів кожен.
Інші алгоритми досягають часу виконання O (log log n) іншими способами. Інтерполяційний пошук очікував, що час виконання O (журнал журналу n) знайде число в відсортованому масиві, але аналіз досить задіяний. Зрештою, аналіз працює, показуючи, що кількість ітерацій дорівнює числу k таким, що n 2 -k ≤ 2, для якого журнал log n є правильним рішенням. Деякі алгоритми, як -от алгоритм MST Шерітона-Тарджана , досягають часу виконання, що включає O (log n), вирішуючи складну задачу з оптимізацією.
Сподіваюся, це допомагає!
Один із способів бачити фактор O (log log n) у часовій складності - це поділ, як речі, пояснені в іншій відповіді, але є інший спосіб побачити цей фактор, коли ми хочемо здійснити торгівлю між часом та простором / часом і наближення / час і твердість / ... алгоритмів, і ми маємо деяку штучну ітерацію нашому алгоритмі.
Наприклад, SSSP (єдиний найкоротший шлях) має алгоритм O (n) на плоских графах, але перед цим складним алгоритмом був набагато простіший алгоритм (але все ще досить важкий) із часом виконання O (n log log n), Основа алгоритму полягає в наступному (просто дуже приблизний опис, і я пропоную пропустити розуміння цієї частини і прочитати іншу частину відповіді):
Але моя думка полягає в тому, що тут ми вибираємо поділ розміром O (log n / (log log n)). Якщо ми виберемо інші підрозділи, такі як O (log n / (log n) ^ 2), який може працювати швидше і принесе інший результат. Я маю на увазі, що у багатьох випадках (як, наприклад, алгоритми наближення чи рандомізовані алгоритми, або алгоритми типу SSSP як вище), коли ми повторюємо щось (підпроблеми, можливі рішення, ...), ми вибираємо кількість ітерацій, що відповідають торгівлі цим ми маємо (час / простір / складність алгоритму / постійний коефіцієнт алгоритму, ...). Тож, можливо, ми бачимо складніші елементи, ніж "log log n" у реальних робочих алгоритмах.