Що саме означає O (log n)?


2139

Я дізнаюся про час роботи 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, але я не можу зрозуміти, як ідентифікувати функцію з логарифмічним часом.


60
Бінарне дерево з двома вузлами має висоту log2 (1) +1 = 1, дерево з двома вузлами має висоту log2 (2) +1 = 2, дерево 4-вузла має висоту log2 (4) +1 = 3, і так далі. Дерево n-вузла має висоту log2 (n) +1, тому додавання вузлів до дерева змушує його середню висоту зростати логарифмічно.
David R Tribble

36
Одне, що я бачу в більшості відповідей, - це те, що вони по суті описують "O (щось)" означає, що час роботи алгоритму зростає пропорційно "щось". Враховуючи, що ви запитували "точне значення" "O (log n)", це неправда. Це інтуїтивний опис нотації Big-Theta, а не Big-O. O (log n) інтуїтивно означає, що час роботи зростає максимально пропорційно "log n": stackoverflow.com/questions/471199/…
Мехрдад Афшарі

31
Я завжди пам’ятаю поділ і перемогу як приклад для O (log n)
RichardOD,

14
Важливо усвідомити, що його база журналів 2 (а не основа 10). Це відбувається тому, що на кожному кроці в алгоритмі ви видаляєте половину решти варіантів. У інформатиці ми майже завжди маємо справу з базою журналів 2, оскільки можемо ігнорувати константи. Однак є деякі винятки (тобто час запуску квадратурного дерева - це база журналу 4)
Етан,

13
@Ethan: Неважливо, в якій базі ви перебуваєте, оскільки перетворення бази - це лише постійне множення, формула - log_b (x) = log_d (x) / log_d (b). Log_d (b) буде просто константою.
mindvirus

Відповіді:


2709

Я не можу зрозуміти, як ідентифікувати функцію з часом входу.

Найпоширенішими атрибутами логарифмічної функції часу є:

  • вибір наступного елемента, на якому потрібно виконати якусь дію, є однією з кількох можливостей, і
  • потрібно буде вибрати лише одного.

або

  • елементами, над якими виконується дія, є цифри n

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

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


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

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

  • O (1) (в гіршому випадку): З огляду на сторінку, на якій вказано ім'я компанії, та назву компанії, знайдіть номер телефону.

  • O (1) (в середньому випадку): Враховуючи сторінку, на якій вказано ім’я людини, та її ім'я, знайдіть номер телефону.

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

  • O (n): Знайдіть усіх людей, чиї номери телефонів містять цифру "5".

  • O (n): надавши номер телефону, знайдіть особу чи компанію з цим номером.

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

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

  • O (n журнал n): Ми хочемо персоналізувати телефонну книгу, тому ми збираємось знайти ім’я кожної людини чи компанії в їх призначеній копії, потім обведемо їх ім’я в книзі та напишемо коротку подячну записку за їх заступництво .

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

  • O (n · n!): Ми готові завантажити телефонні книги на транспортний док. На жаль, робот, який повинен був завантажувати книжки, пішов безпроблемно: він кладе книги на вантажівку у випадковому порядку! Ще гірше, що він завантажує всі книги на вантажівку, потім перевіряє, чи вони в правильному порядку, а якщо ні, то вивантажує їх і починає спочатку. (Це страшний вид бого .)

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


81
@cletus: Супутні, боюся. Я вибрав це тому, що в телефонних книгах є велика кількість N, люди розуміють, що вони і що роблять, і тому, що це є універсальним прикладом. Плюс мені довелося використовувати роботи в моєму поясненні! Виграш багатоборство. (Крім того, схоже, що ваша відповідь була зроблена ще до того, як я навіть був учасником StackOverflow для початку!)
Джон Feminella

12
"В офісі сталася помилка, і кожен запис у кожній із телефонних книжок має додаткові" 0 "в кінці номера телефону. Візьміть кілька вибілів та видаліть кожен нуль." <- це не порядок N квадрата. N визначається як розмір вводу. Розмір вводу - це кількість номерів телефонів, яка є числом номерів на книгу, меншим за кількість книг. Це все ще лінійна операція в часі.
Біллі ONeal

21
@Billy: У цьому прикладі N- кількість людей в одній книзі. Оскільки кожна людина в телефонній книзі також отримує власну копію книги, є N однакові телефонні книги, кожна з Nлюдьми в ній, яка є O (N ^ 2).
Джон Фемінелла

48
Хіба O (1) не найкращий випадок, а не найгірший випадок, як це дивно виділено?
Свип

54
Мені знадобилося O (long⅝n! N-55/2) час, щоб знайти визначення O (log n), яке, нарешті, має сенс. +1
iAteABug_And_iLiked_it

611

O(log N)в основному означає, що час іде лінійно вгору, тоді як nіде вгору експоненціально. Отже, якщо 1для обчислення 10елементів знадобиться друге, для обчислення елементів знадобиться 2секунди 100, 3для обчислення 1000елементів тощо.

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


108
Три рядки мудрості, які перемагають усі інші відповіді есе ... :) На всякий випадок, якщо хтось цього не вистачає, в контексті програмування база журналу становить 2 (а не 10), тож O (log n) масштабується як 1 сек на 10 елементи, 2 сек за 20, 3 за 40 тощо
nawfal

3
Погоджений, стислий і зрозумілий, хоча закінчувальне запитання в ОП полягало в тому, як визначити логарифмічну функцію, не зовсім «що це таке»
Адам

4
так, логарифмічна функція - це зворотне до експоненціальної функції. ((log x) база a) обернена (a x). Якісний аналіз цих функцій із графіками дав би більше інтуїції.
переобмін

7
Це знадобило мені близько 3-х перечитань, щоб зрозуміти, що це було не так. Час лінійно йде вгору, тоді як кількість елементів експоненціальне. Це означає більше елементів за менший час . Це ментально оподатковує тих, хто візуалізує logяк звичну криву журналу на графіку.
Qix - МОНІКА ПОМИЛИЛА

1
Я думаю, що це дуже хороша відповідь, за винятком тієї частини, де він стверджує, що двійковий пошук - це алгоритм розділення та підкорення. Це не так.
code_dredd

579

На це питання вже розміщено багато хороших відповідей, але я вважаю, що насправді не вистачає важливого, а саме - ілюстрованої відповіді.

Що означає говорити про те, що висота повного двійкового дерева дорівнює O (log n)?

На наступному малюнку зображено двійкове дерево. Зверніть увагу, як кожен рівень містить подвійну кількість вузлів порівняно з рівнем вище (отже, двійковий ):

Двійкове дерево

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

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

Накреслення log(n)на звичайному аркуші паперу призведе до появи графіка, де зростання кривої уповільнюється зі nзбільшенням:

O (журнал n)


60
"Зверніть увагу, як кожен рівень містить подвійну кількість вузлів порівняно з рівнем вище (отже, двійковий)" Це неправильно. Те, що ви описуєте, - це збалансоване двійкове дерево. Бінарне дерево означає, що кожен вузол має максимум двох дітей.
Онотрія

8
Насправді це дуже особливе збалансоване двійкове дерево, яке називається повним бінарним деревом. Я відредагував відповідь, але мені потрібно, щоб хтось її затвердив.
user21820

5
Для повного бінарного дерева не потрібно мати останній рівень, щоб бути повністю заповненим. Я б сказав, «повне бінарне дерево» є більш підходящим.
Пан AJ

Ваша відповідь намагається відповісти конкретніше на початкову проблему ОП, тому вона краще, ніж поточна прийнята відповідь (ІМО), але вона все ще дуже неповна: ви даєте лише половину прикладу та 2 зображення ...
nbro

2
У цьому дереві 31 елемент, а не 16. Чому його називають набором даних 16 елементів? Кожен вузол на ньому позначає число, інакше це буде неефективне бінарне дерево: P
Perry Monschau

245

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

Бінарне дерево - це випадок, коли проблема розміру n ділиться на підпроблему розміру n / 2, поки ми не дійдемо до задачі розміру 1:

висота двійкового дерева

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

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


2
новачок тут. Тож чи можна сказати, що висота дерева - це швидкість поділу за допомогою рекурсії, щоб досягти розміру n = 1?
Коді

@Cody, так, здебільшого ваше спостереження є точним. Цей приклад ілюструє / використовує log_2. Ваші спостереження витратять далі log_2і будуть точними для будь-якого log_xмісця x > 1. Проведення прямого поділу може не призвести до точного 1, тому ви можете сказати рекурсивний поділ, поки Ceiling()останнє ділення не дорівнює 1, або щось подібне.
Джеймс Оравець

198

Огляд

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

По-перше, вам захочеться мати загальне уявлення про логарифм, який ви можете отримати на веб-сайті 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.

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

Прості кодові приклади різних категорій Big 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 для циклу кратна поточному значенню i на 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

Цей алгоритм показує варіацію, де він буде надрукувати привіт п / 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). Вкладення циклів для петель допомагає нам отримати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 кубів Приклади:

  • Алгоритм 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";

Підсумок

Наведене вище дає кілька прямих прикладів та варіацій, які допоможуть продемонструвати, які тонкі зміни можуть бути внесені, що насправді не змінюють аналіз. Сподіваємось, це дає достатньо розуміння.


17
Дивовижно. Найкраще пояснення для мене, що я коли-небудь бачив. Було б приємніше, якщо O(n^2)це відзначається як поєднання O(n)і O(n), так O(n) * O(n) = O(n * n) = O(n^2). Це відчуття, як трохи стрибнути без цього рівняння. Це повторення попереднього пояснення, але я думаю, що це повторення може надати читачам більшу впевненість для розуміння.
Еоніл

2
Це просто найкраще коли-небудь пояснення.
Едгар Кіляк

2
@IceTea, щоб дати вам уявлення / інтуїцію вашого питання. Якщо ви складете графік nпроти, n/2ви побачите, що вони обидва роблять пряму лінію. Це ставить їх до одного класу, оскільки вони мають схожі темпи зростання (подумайте про це як форму діаграми). Аналогічно, якщо ви накреслили log_2проти, log_3ви побачите, що вони обидва мають "схожі форми" або "схожі темпи зростання".
Джеймс Оравець

1
@IceTea, Пояснення, надані @Shai та @James, є більш точним, n/2 or 2n or n+2 or nматимуть різний різний рядок у графіку, але вони матимуть однаковий темп зростання, що означає, що всі вони будуть слідувати лінійному зростанню.
Нареш Джоші

2
Як щодо випадку, коли у нас є дві вкладені петлі, але другий ітератор залежить від першого, чи впливає ця залежність на часову складність?
Bionix1441

131

Якщо у вас була функція, яка займає:

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.

Тоді потрібно час журналу 2 (n). Позначення Великий Про , грубо кажучи, означає , що відносини потрібно тільки бути вірно для великих п, і що постійні множники і менші терміни можуть бути проігноровані.


чи log2 (n) те саме, що o (log n)?
Sven van den Boogaart

Так, дивіться коментар nawfal для іншої відповіді тут: (копіювання-вставлення) - в контексті програмування база журналу становить 2 (не 10), тому O (log n) масштабується як 1 сек для 10 елементів, 2 sec для 20 , 3 для 40 тощо
Андрейс

@SvenvandenBoogaart, приклад цього рішення ілюструє log_2, що є в класі O(log(n)). Є багато інших в тому ж класі, O(log(n))тобто log_xдеx > 1
James Oravec

@Andrejs, ваш коментар so O(log n) scales like 1 sec for 10 elements, 2 sec for 20, 3 for 40 etcнеточний. Цей шаблон / клас відповідатиме / не співпадатиме з O(n)не O(log(n)). Якщо хтось зацікавився, log_10то еквівалентним прикладом буде 1 сек на 10 елементів, 2 секунди на 100, 3 на 1000 тощо.
Джеймс Оравець

99

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


1
+1, але ви дійсно повинні зазначити, що це log2, а не log10.
Адріано Варолі Піацца

62
log2 або log10 не має значення. Вони відрізняються лише масштабним коефіцієнтом, що робить їх однакового порядку, тобто вони все ще ростуть з однаковою швидкістю.
Нолдорін

17
Найцікавіше в логарифмах - те, що при порівнянні відносних висот точна база, яку ви використовуєте, не має значення. log 10,000 / log 100це 2 незалежно від того, яку базу ви використовуєте.
Анон.

12
Якщо бути нитковим, O (lg n) означає, що час виконання є максимально пропорційним lg n. Те, що ви описуєте, - Theta (lg n).

1
@rgrig: Це правда. Я відредагував декілька "максимум", щоб вказати на верхню мету характеру big-O.
Анон.

95

Логарифм

Гаразд, спробуємо і повністю зрозуміємо, що таке логарифм насправді.

Уявіть, у нас є мотузка, і ми прив’язали її до коня. Якщо мотузка безпосередньо прив’язана до коня, сила, яку коні потрібно буде відтягнути (скажімо, від людини), безпосередньо 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 спроб, але 129 чисел знадобиться нам не більше 8 спроб (у відношенні до логарифмів тут нам знадобиться 7 здогадок для діапазону значень 128, 10 здогадок для діапазону значень 1024 7 - логарифм 128, 10 - логарифм 1024 (основа 2)).

Зауважте, що у мене є напівжирний шрифт. Нотація Big-O завжди стосується гіршого випадку. Якщо пощастить, ви можете вгадати число за одну спробу, і тому найкращий випадок - це O (1), але це вже інша історія.

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

А як щодо O (n log n)?

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

Ви можете легко визначити, чи алгоритмічний час n n n. Шукайте зовнішню петлю, яка повторюється через список (O (n)). Потім подивіться, чи є внутрішня петля. Якщо внутрішній цикл вирізає / зменшує набір даних для кожної ітерації, це цикл (O (log n)), і тому загальний алгоритм = O (n log n) .

Відмова: Приклад мотузкового логарифму був узятий із чудової книги Захоплення Математика У. Сойєра .


In our example above, our 'growth rate' is O(log n). For every additional loop, the force our rope can handle is 10 times more, підтримується діаграмою, яка показує n == кількість петель і our 'growth rate'=> 10 ^ n, що НЕ log n. Приклад можна зробити правильним, зробивши n=# horses, для чого потрібно стримувати n n циклів. Погані педогогічні приклади дають учням, які лише вірять, що розуміють.
psimpson

56

Ви можете думати про O (log N) інтуїтивно, кажучи, що час пропорційний кількості цифр у N.

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

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

І так далі.


7
Я вважаю, що досить точний і легший для розуміння, ніж більшість пояснень.
Т.

це пояснення log<sub>10</sub> N, чи не так?
LiuYan 刘 研

1
@LiuYan 刘 研 вони не сказали, в якій базі знаходилася кількість цифр. Однак у будь-якому випадку, log₂ (n) = log₁₀ (n) / log and (2) та 1 / log is (2) є постійним множником, з тим же принципом, що стосується всіх інших баз. Це показує дві речі. По-перше, принцип місячної тіні застосовується незалежно від основи (хоча чим нижча база, тим менше "задирок" в оцінці), а також, що O (log n) є O (log n), незалежно від того, на якій основі розрахунок, який привів вас до цього висновку .
Джон Ханна

"пропорційна" ... "кожна з яких вдвічі зменшує розмір введення" ??????
csguy

52

Найкращий спосіб, який мені завжди доводилося подумки уявляти алгоритм, який працює в O (log n), полягає в наступному:

Якщо збільшити розмір проблеми на мультиплікативну суму (тобто помножити її розмір на 10), робота збільшується лише на суму добавки.

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


52

Спочатку рекомендую прочитати наступну книгу;

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

Ось деякі функції та їх очікувані складності. Числа позначають частоту виконання операторів .

Ось деякі функції та їх очікувані складності

Слідкуючи за діаграмою складності Big-O, також взятою з бігочехету Діаграма складності Big-O

Нарешті, дуже проста вітрина показує, як вона обчислюється;

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

Аналіз часу виконання програми (приклад).

Аналіз часу виконання програми


5
Я б не поклав O (n log n) у поганий кошик. Він належить до справедливого .
Андре Верланг

Під час перегляду діаграми складності з великим O (вище) ви повинні пам'ятати, що O (n) - це фактична лінійна точка, а не рожево-оранжевий бордюр. @Andre Ось чому O (n log n) правильно позначений у дужці "поганої" продуктивності, це гірша продуктивність, ніж лінійна.
JavaBeast

@JavaBeast правильний, тоді як продуктивність O (n log n) технічно гірша, ніж O (n), зверніться до таблиці вище, де представлено хороше їх порівняння (див. Зростання двох). отох діаграма, з іншого джерела, суперечлива, оскільки вона ставить O (1) і O (log n) в однакові добрі / відмінні. їх відносний порядок зростання порівнянний з O (n) та O (n log n). tl; dr; O (n log n) не є відмінним, але далеко не поганим.
Андре Верланг

1
Ця відповідь неправильна! Це передбачає, що N = N * N. Насправді N = N! Ваш приклад насправді N кубиків. Ви робите те саме у своєму графіку. Ваш O (n) насправді повинен бути розривом між жахливим і поганим. Математичний доказ: Ви говорите, що для циклу константа з O (1). Ось що означає 1 дійсно, не залежить від N. Це просто означає, що не є змінним. Але він мінливий, оскільки залежить від N. Двічі N та половини часу. Тому він недійсний. Якщо це з тієї книги, не купуйте її! Графік коду, який ви показали, не справжній, це жарт, дивіться, "Theesome", це означає, що троє людей мають секс одразу! О Боже мій
jgmjgm

1
Чи не повинен O (n) бути по діагоналі?
gyosifov

46

Що таке журнал b (n)?

Це кількість разів, коли можна розрізати колоду довжиною n повторно на b рівних частинах, перш ніж досягти ділянки розміром 1.


Відмінний коментар! Це лаконічна і точно відповідь, яку я шукаю.
DennisL

18

Алгоритми ділення та підкорення зазвичай мають a logn компонент до часу виконання. Це відбувається від повторного скорочення вдвічі.

У разі двійкового пошуку, при кожній ітерації ви викидаєте половину вводу. Слід зазначити, що в нотації Big-O, журнал - це база журналів 2.

Редагувати: Як зазначалося, база журналу не має значення, але при виведенні продуктивності алгоритму Big-O фактор журналу вийде вдвічі, отже, чому я вважаю його базовим 2.


2
Чому це журнал бази 2? Наприклад, у рандомізованому кварцовому корі, я не думаю, що це база 2. Наскільки я знаю, база не має значення, оскільки база журналів a (n) = log2 (n) / log2 (a), тому кожен логарифм відрізняється від іншого постійною, а константи ігноруються в нотації big-o. Насправді, написання основи журналу в big-o нотації є моєю помилкою, оскільки ви пишете константу.
IVlad


Дуже вірно, що він може бути перетворений на будь-яку базу, і це не має значення, але якщо ви намагаєтеся отримати продуктивність Big-O і бачите постійне скорочення вдвічі, це допомагає зрозуміти, що ви не бачите базу журналу 10, відображеної в коді.
Девід Канарек

Відсторонення: у таких речах, як B-дерева, де у вузлів є вентилятор більше 2 (тобто "ширший", ніж двійкове дерево), ви все одно побачите зростання O (logn), оскільки це все ще ділиться і -конуйте, але основа журналу буде пов’язана з вентилятором.
Роджер Ліпскомб

Фактично, відступ у журналі 2 був дуже корисним.
Дан

15

Але що саме таке O (log n)? Наприклад, що означає сказати, що висота> повного бінарного дерева дорівнює O (log n)?

Я б перефразував це як "висота повного двійкового дерева - це log n". Визначити висоту повного двійкового дерева було б O (log n), якби ви проходили крок за кроком.

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

Логарифм - це, по суті, обернена експоненція. Отже, якщо кожен "крок" вашої функції - це усунення фактора елементів з початкового набору елементів, це логарифмічний алгоритм часу.

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


3
+1 для згадування "Логарифм - це, по суті, зворотна експоненція".
талонкс

12

Ці 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);
    }

Я впевнений, що мені чогось не вистачає, але чи не завжди я буду нульовим, і петлі працюватимуть назавжди в обох випадках, оскільки 0 * 2 = 0 і 0/2 = 0?
dj_segfault

2
@dj_segfault, це була моя помилка. Я думаю, зараз це має сенс .. :)
Раві Бісла

@RaviBisla Інші відповіді стверджують, що введення 10 займе 1 раз стільки, скільки 10 циклів, а введення 100 - 3 рази більше часу введення 1, що, безумовно, не стосується цих прикладів. stackoverflow.com/a/2307330/1667868
Sven van den Boogaart

12

O (log n) трохи вводить в оману, точніше, це O (log 2) n), тобто (логарифм із базою 2).

Висота врівноваженого двійкового дерева становить O (log 2 n), оскільки кожен вузол має два (відмітьте "два", як у журналі 2 n) дочірні вузли. Отже, дерево з n вузлами має висоту log 2 n.

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


4
O (log n) - той самий порядок, що і O (ld n) або O (LN n). Вони пропорційні. Я розумію, що для навчальних цілей простіше використовувати ld.
геліос

4
"точніше, це O (ld n)" - Ні, це не так: всі журнали мають однаковий порядок (кожен відрізняється від інших лише деяким коефіцієнтом постійного масштабування, який ігнорується / ігнорується).
ChrisW

1
ти прав, Кріс, дуже погана формулювання. повинен був сказати це так, як це зробили геліоси. це допомагає для навчання / розуміння, але, нарешті, всі журнали в одному порядку.
stmax

10

O(log n) посилається на функцію (або алгоритм, або крок в алгоритмі), що працює в проміжок часу, пропорційний логарифму (як правило, база 2 в більшості випадків, але не завжди, і в будь-якому випадку це несуттєво за позначенням big-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, за визначенням , константи не мають значення. Крім зміни базового правила для логарифмів, єдина різниця між логарифмами різних основ є постійним фактором.


Заключна примітка * вирішила мою плутанину щодо логарифмів, заснованих на 2 або 10 :) Дякую.
yahya


9

Простіше кажучи: на кожному кроці алгоритму ви можете скоротити роботу навпіл. (Асимптотично рівнозначне третьому, четвертому, ...)


2
Ця відповідь дуже неточна. Перш за все, можна подумати розрізати твір навпіл лише у випадку логарифму в основі 2. Дійсно неймовірно, як ця відповідь (і більшість відповідей на початкове запитання) отримала стільки голосів. "(Асимптотично еквівалентний третьому, четвертому, ...)"? Навіщо відповідати на запитання, якщо у вас немає часу?
nbro

8

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

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


7

Але що саме таке 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 + b log (n) + c n + d n n

... тоді це буде O (n квадрат), тому що, незалежно від значень констант a, b, c і ненульових d, d*n*nтермін завжди буде домінувати над іншими при будь-якому досить великому значенні n.

Ось що означає позначення біт O: воно означає "який порядок домінуючого терміна для будь-якого досить великого n".



7

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

Тепер, якщо ви можете довести, що при кожній ітерації вашого алгоритму ви відрізаєте частину цього простору, тобто не менше деякої межі, це означає, що ваш алгоритм працює в O (logN) час.

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


6

Я можу навести приклад для циклу 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) (істота, яка є постійною).


6

Насправді, якщо у вас є список з 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)


2
Поки якась зловмисна програма не почне вставляти новий список з довжиною x на двох рівнях до вузлів листя. Тоді, здається, це буде нескінченна петля ...
Френсіс Куглер,

1
Я не отримав вашого коментаря. Чи моє пояснення неправильне?
Дінаїз

1
Я лише жартував гіпотетично. Я насправді нічого не означав.
Френсіс Куглер,

6

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

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

Оскільки складність часу залежить від різних параметрів, а саме.
1. Фізична система
2. Мова програмування
3. Стиль кодування
4. І багато іншого ......

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


Замість цього ми беремо розмір введення як параметр, оскільки який би код не був, вхід є однаковим. Отже час виконання - це функція від розміру вводу.

Далі наводиться приклад лінійного алгоритму часу


Лінійний пошук
З огляду на п ять вхідних елементів, для пошуку елемента в масиві потрібно не більше, ніж 'n' порівнянь . Іншими словами, незалежно від того, якою мовою програмування ви користуєтесь, який стиль кодування ви надаєте перевагу, в якій системі ви його виконуєте. У гіршому випадку потрібно лише порівняння n. Час виконання лінійно пропорційний розміру вводу.

І це не просто пошук, якою б не була робота (приріст, порівняння чи будь-яка операція), це функція розміру вводу.

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

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

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

Побачте, як збільшується розмір вводу, збільшується виконана робота і вона не залежить від будь-якої машини. І якщо ви спробуєте дізнатись значення одиниць роботи, це насправді залежить від тих, хто вище зазначених параметрів. Він зміниться відповідно до систем та всіх.


5

Дерево

log x to base b = y є зворотним b^y = x

Якщо у вас є дерево A-глибини глибини d та розміру n, то:

  • обхід всього дерева ~ O (M ^ d) = O (n)

  • Ходьба єдиним шляхом у дереві ~ O (d) = O (log n до основи M)


5

В інформаційних технологіях це означає, що:

  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.

Здається, що це позначення здебільшого взяли з математики.

У цій статті є цитата: Де Кнут, "ВЕЛИКИЙ ОМИКРОН І ВЕЛИКА ОМЕГА І ВЕЛИКА ТЕТА", 1976 :

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

Сьогодні 2016 рік, але ми використовуємо його і сьогодні.


У математичному аналізі це означає, що:

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

Але навіть у математичному аналізі іноді цей символ вживався у значенні "C * g (n)> f (n)> 0".

Як я знаю з університету, символ був індукований німецьким математиком Ландау (1877-1938)


3

Повний бінарний приклад - O (ln n), оскільки пошук виглядає так:

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

Якщо шукати 4, ви отримуєте 3 хіти: 6, 3 потім 4. І log2 12 = 3, що є хорошим підсумком кількості звернень, де потрібно.


дякую за приклад. Це чітко говорить про те, як наш алгоритм може використовувати логарифмічний час у методі ділення та перемоги.
Abc

Отже, якщо його цикл n / 2, його завжди log (n)?
Гіл Бейрут

3

Якщо ви шукаєте відповідь на основі інтуїції, я хотів би скласти для вас дві інтерпретації.

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

  2. Уявіть алгоритм, який приймає ціле число, 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) час.


будь ласка, відредагуйте. має "O (n) або theta (n)" в обох сценаріях ...? Крім того, я чув це багато, розмір проти # цифр. Ми говоримо розмір === 128 для n = 10000000 і цифр === 8 для n = 10000000? Будь ласка, з’ясуйте.
Коді

2

Алгоритми в парадигмі ділення та перемоги мають складність 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-ac-program-to-calculate-powxn/

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