English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

nu

гість
1 / ?
назад до уроків

Темпи зростання, а не абсолютні вартості

Big O: вимірювання темпів зростання вартості алгоритму

Нотація Big O вимірює темп зростання вартості алгоритму — не абсолютну вартість.

Питання, на яке відповідає Big O: коли розмір входу N подвоїться, чи подвоїться й робота? Чи учетверітиметься? Чи залишиться незмінною?

Буква 'O' означає 'порядок величини'. Вираз у дужках описує форму кривої зростання.

Таблиця Big O: операції при N=10, 100 і 1 000 для O(1), O(N) і O(N²)

Ключові класи складності:

- O(1) — постійна: вартість не зростає. Приклад: пошук значення за індексом у масиві. Чи у масиві 10 елементів чи 10 мільйонів, один пошук залишається одним пошуком.

- O(N) — лінійна: вартість зростає зі входом. Приклад: читання кожного елемента списку один раз. Подвойте список, подвойте читання.

- O(N²) — квадратична: вартість зростає як квадрат входу. Приклад: порівняння кожного елемента з кожним іншим елементом. Подвойте N, учетверітеся робота.

Таблиця порівняння темпів зростання:

NO(1)O(N)O(N²)
10110100
100110010 000
1 00011 0001 000 000

При N=10 різниця виглядає малою. При N=1 000 розрив стає величезним.

Порівняйте O(N) та O(N²)

Використовуйте таблицю порівняння темпів зростання вище.

При N=1 000: O(N) вимагає 1 000 операцій. O(N²) вимагає 1 000 000 операцій.

При N=1 000 скільки разів більше операцій потребує O(N²) у порівнянні з O(N)? Покажіть роботу.

Як структура коду розкриває складність

Як визначити Big O з коду

Big O приховується в формі вашого коду. Чотири закономірності охоплюють більшість випадків:

Одиничний цикл над N елементів: O(N)

# O(N): один прохід через список
for item in list_of_n_items:
    process(item)

Вкладені цикли, кожен над N елементів: O(N²)

# O(N²): кожен елемент спарований з кожним іншим елементом
for item_a in list_of_n_items:
    for item_b in list_of_n_items:
        compare(item_a, item_b)

Пошук за постійний час: O(1)

Доступ до індексу масиву, пошук у хеш-таблиці — один крок незалежно від розміру.

Розділяй і вторюй (скорочуй задачу навпіл на кожному кроці): O(log N)

Бінарний пошук: кожна перевірка скорочує залишилися елементи.

---

Приховане O(N²): список у циклі

# Це виглядає як O(N) але це насправді O(N²)
visited = []
for item in list_of_n_items:
    if item not in visited:   # скануватися весь visited: O(N)
        visited.append(item)  # весь цикл: O(N²)

Рядок if item not in visited скануватися кожен елемент visited на кожній ітерації. Сканування списку коштує O(N). Цикл який запускається N разів, кожен роблячи O(N) роботи: O(N) × O(N) = O(N²).

Це Комбінація з'являється в 1 000+ проектів з відкритим кодом. Виправлення займає один символ: замініть visited = [] на visited = set(). Перевірка приналежності набору коштує O(1), не O(N). Одна зміна. Такі ж результати. В 1 000 разів швидше при N=1 000.

Класифікуйте й виправте цей код

Прочитайте цей код:

result = []
for name in student_names:
    if name not in result:
        result.append(name)
Яка Big O складність цього коду? Поясніть, чому рядок `if name not in result` робить його дорогим. Потім перепишіть код щоб зробити його O(N).

Теорія зустрічає практику

Big O в дикій природі

Big O не просто теорія. Вона відокремлює програми які закінчуються за секунди від програм які займають 17 хвилин — на тому ж завданні.

Реальний приклад: виявлення циклу залежності в системі побудови.

Коли ви встановлюєте програмне забезпечення, ваш комп'ютер розв'язує граф залежностей: пакет A потребує B, B потребує C, й так далі. Система побудови перевіряє цей граф на цикли.

Алгоритм виявлення циклу O(N²) працює добре при N=100 пакетів. При N=50 000 пакетів (реальний проект): це займає 17 хвилин. Виправлення O(N): 10 секунд.

Цей точний дефект існує в GHC (компілятор Haskell), pip (менеджер пакетів Python), Maven (система побудови Java), Cargo (менеджер пакетів Rust), & 1 000+ інших проектів.

Не тому що їх автори були необережні. visited = [] було написано коли N був малим. Код закристалізувався. N виріс. Ніхто не помітив доки побудова не займала пів години.

Big O це словник який дозволяє вам назвати що сталося — & виправити це.

---

Хочете заглибитися далі? Наш курс unhamming включає повну главу про Big O, MOAD-0001 (реальний дефект O(N²) знайдений в 1 000+ проектів з відкритим кодом), & чому назвати закономірність дозволяє вам знайти її везде. Див. Відсутня глава: складність алгоритмів.

Передбачте часи побудови

Система побудови використовує виявлення циклу O(N²).

Виміряні часи побудови:

- N=100 пакетів: 0,01 секунди

- N=1 000 пакетів: 1 секунда

Для O(N²): час масштабується як (N_new / N_old)².

Для O(N): час масштабується як (N_new / N_old).

Використовуючи ці формули й виміряні дані: (A) при N=10 000, скільки часу займає версія O(N²)? (B) після виправлення O(N), використовуючи N=1 000 як вашу базову лінію, скільки часу займає версія O(N) при N=10 000? Покажіть роботу для обох.