Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке експоненційний пошук (exponential search)?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Експоненційний пошук (exponential search)** - алгоритм пошуку у відсортованому масиві, який спочатку експоненційно розширює робочий діапазон (1, 2, 4, 8, ...), поки не "перестрибне" цільовий елемент, а потім виконує бінарний пошук усередині знайденого діапазону. **Ключове:** час роботи - O(log i), де i - позиція шуканого елемента (у найгіршому випадку O(log n)), і алгоритм потребує довільного доступу та відсортованості даних.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь Експоненційний пошук (exponential search) - це алгоритм пошуку у відсортованому масиві, який спочатку експоненційно розширює робочий діапазон (1, 2, 4, 8, ...), поки не "перестрибне" цільовий елемент, а потім виконує бінарний пошук усередині знайденого діапазону. Час роботи - O(log i), де i - позиція шуканого елемента; у найгіршому випадку - O(log n). Потребує довільного доступу та відсортованості даних. ## Детальний розбір ### Ідея алгоритму Якщо масив відсортований за зростанням, можна швидко "оцінити" приблизний діапазон, де може перебувати елемент. Для цього ми перевіряємо індекси, що зростають експоненційно: 1, 2, 4, 8, ... Зупиняємось, коли зустріли елемент, не менший за цільовий, або вийшли за межі масиву. Після цього запускаємо звичайний бінарний пошук усередині цього діапазону. ### Кроки алгоритму 1. Перевірити перший елемент: якщо дорівнює цілі - повернути індекс 0. 2. Ініціалізувати bound = 1 і подвоювати: 1, 2, 4, 8, … поки bound < n і arr[bound] < target. 3. Визначити межі для бінарного пошуку: left = bound / 2 (округлення вниз), right = min(bound, n - 1). 4. Виконати бінарний пошук у [left, right]. Знайти індекс або повернути -1, якщо елемента немає. ### Складність - Час: O(log i), де i - індекс цілі; у найгіршому випадку O(log n). Експоненційний етап - O(log i), бінарний етап - O(log i). - Пам'ять: O(1) додаткової пам'яті. ### Коли застосовувати - Відсортовані масиви зі швидким довільним доступом (наприклад, звичайні масиви в пам'яті). - Структури, де довжина невідома заздалегідь або логічно "нескінченна" (наприклад, інтерфейси доступу, що повертають значення за індексом, але не дають розмір; часто трапляється в задачах на співбесідах). - Сценарії, коли ціль передбачається "близько до початку" - експоненційне зростання швидко локалізує невеликий діапазон. ### Переваги та обмеження - Плюси: швидше локалізує діапазон порівняно з лінійним пошуком; не потребує знання довжини масиву; теоретично може бути ефективнішим за звичайний бінарний, якщо ціль перебуває близько до початку (менший логарифм від i, а не від n). - Мінуси: потребує відсортованості та довільного доступу; на структурі з дорогим доступом за індексом (наприклад, зв'язані списки) незастосовний; при множинних повторах повертає довільний індекс, якщо не модифікувати бінарний етап для пошуку лівої межі. ### Приклад коду (JavaScript) ```js function exponentialSearch(arr, target) { const n = arr.length; if (n === 0) return -1; if (arr[0] === target) return 0; // Експоненційне розширення діапазону let bound = 1; while (bound < n && arr[bound] < target) { bound *= 2; } const left = Math.floor(bound / 2); const right = Math.min(bound, n - 1); return binarySearchInRange(arr, target, left, right); } function binarySearchInRange(arr, target, left, right) { while (left <= right) { const mid = left + ((right - left) >> 1); if (arr[mid] === target) return mid; // Для першої позиції див. варіант нижче if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } // Варіант, що повертає індекс ПЕРШОГО входження при дублікатах function binarySearchFirst(arr, target, left, right) { let ans = -1; while (left <= right) { const mid = left + ((right - left) >> 1); if (arr[mid] >= target) { if (arr[mid] === target) ans = mid; right = mid - 1; } else { left = mid + 1; } } return ans; } // Приклад використання: // const idx = exponentialSearch([1,3,5,7,9,12,15,18,21], 12); // => 5 ``` ### Покроковий приклад Масив: [1, 3, 5, 7, 9, 12, 15, 18, 21, 24, 27, 30], ціль: 18. 1. Перевіряємо arr[0] = 1 ≠ 18. 2. bound = 1: arr[1] = 3 < 18 → bound = 2. 3. bound = 2: arr[2] = 5 < 18 → bound = 4. 4. bound = 4: arr[4] = 9 < 18 → bound = 8. 5. bound = 8: arr[8] = 21 ≥ 18 → діапазон знайдено: [left = 4, right = 8]. 6. Бінарний пошук у [4, 8]: mid = 6 → arr[6] = 15 < 18 → left = 7; mid = 7 → arr[7] = 18 → знайдено, індекс 7. ### Варіації та практичні поради - Для масивів з дублікатами використовуйте бінарний пошук лівої/правої межі, щоб повернути перше/останнє входження. - Якщо порядок спадний, інвертуйте умови порівнянь на обох етапах. - При невідомому розмірі колекції використовуйте безпечний доступ з обробкою виходу за межі (наприклад, API може повертати +∞/undefined при зверненні за межі). Подвоюйте bound до "сигналу" виходу, потім бінарний пошук в останньому валідному діапазоні. ### Перевірка крайових випадків - Порожній масив → повернути -1. - Ціль менша за перший елемент → бінарний етап у вузькому діапазоні [0, 0]. - Ціль більша за всі елементи → right буде n - 1; бінарний етап коректно поверне -1.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.