1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

# теория · шаг 3 из 6

Подстановка: угадать и доказать индукцией

Коротко

Дерево ДОГАДЫВАЕТСЯ об ответе, а метод подстановки его ДОКАЗЫВАЕТ. Схема: угадать форму ответа (обычно из дерева), предположить, что она верна для меньших входов, подставить в рекуррентность и показать, что для n она тоже держится - подобрав константу. Это обычная индукция из первого раздела, только по размеру входа. Ею и закрывают ответ, которому дерево лишь намекнуло.

Если умеешь доказать оценку рекуррентности подстановкой (угадать форму, предположить для n/2, подставить) - листай до «Теперь сам».

Как думаешь, доказали ли мы n·log n

Дерево подсказало: T(n) = 2·T(n/2) + n это Θ(n·log n). Но «подсказало» - не «доказало»: мы на глаз сложили уровни, на глаз сосчитали их число, на глаз учли листья. А что, если где-то ошиблись на множитель? Нужен способ проверить ответ строго, без картинок. Он есть, и это индукция: предположить, что оценка верна для входов поменьше, и вывести её для n.

На что это похоже

Это ровно индукция из раздела про правильность, только шаг идёт по размеру входа. Рекурсивный вызов T(n/2) читается как «расписка на n/2 уже погашена ровно на столько, сколько мы утверждаем». Подставляешь это обещание в формулу для n и проверяешь, что арифметика сходится - что для n выходит не больше обещанного. Сошлась - оценка доказана для всех n сразу.

Механизм: угадать, предположить, подставить

Три шага. Угадать форму ответа - T(n) ≤ c·n·log₂ n для какой-то константы c. Предположить индукцией, что она верна для меньших входов, в частности для n/2: T(n/2) ≤ c·(n/2)·log₂(n/2). Подставить это в рекуррентность и показать, что для n неравенство держится:

T(n) = 2·T(n/2) + n
     ≤ 2·[c·(n/2)·log₂(n/2)] + n      (подставили предположение)
     = c·n·log₂(n/2) + n
     = c·n·(log₂ n - 1) + n            (log₂(n/2) = log₂ n - 1)
     = c·n·log₂ n - c·n + n
     = c·n·log₂ n - (c-1)·n
     ≤ c·n·log₂ n                      при c ≥ 1

Последний шаг закрывает индукцию: (c-1)·n ≥ 0 при c ≥ 1, поэтому вычитаемое -(c-1)·n неположительно и только уменьшает левую часть. Значит она тем более не больше c·n·log₂ n, и отбрасывание этого слагаемого сохраняет неравенство ≤. Итог: T(n) ≤ c·n·log₂ n для всех n - T(n) = O(n·log n), доказано.

Правило

Подстановка: (1) угадай форму ответа с неизвестной константой; (2) предположи, что она верна для меньших входов; (3) подставь в рекуррентность и подбери константу так, чтобы неравенство для n замкнулось. Плюс проверь базу. Дерево даёт догадку, подстановка - доказательство.

Разбор: база не на единице

У доказательства есть тонкость с базой. При n = 1 оценка c·n·log₂ n = c·1·0 = 0, а T(1) - положительная константа, 0 ≥ T(1) неверно. Значит база на единице не годится. Берут базу побольше - n = 2: T(2) это какая-то константа, а c·2·log₂ 2 = 2c, и c берут настолько большим, чтобы 2c ≥ T(2). Индукция же всё равно применяется к n ≥ 4 (сводит к n/2 ≥ 2), поэтому маленькие входы можно закрыть выбором c. Асимптотика про большие n, и стартовать индукцию с двойки, а не с единицы, - законно.

Разбор: подстановка ловит неверную догадку

Пусть кто-то предположил, что T(n) = 2·T(n/2) + n это O(n) - линия. Проверим подстановкой: предположим T(n/2) ≤ c·(n/2), тогда

T(n) ≤ 2·c·(n/2) + n = c·n + n = (c+1)·n

Вышло (c+1)·n, а надо было c·n - на n больше, чем обещали. Замкнуть не удаётся ни при каком c: лишнее +n не исчезает. Значит догадка O(n) неверна, и подстановка это показала честно, без картинок. Именно поэтому ей доверяют больше, чем дереву: она либо смыкается, либо нет, и «на глаз» тут ничего не спрячешь.

Верная догадка c·n·log₂ n смыкается ровно потому, что при подстановке лишним выходит −(c−1)·n - слагаемое со знаком минус, которое неравенство только усиливает. У заниженной c·n лишнее слагаемое +n идёт с плюсом и тянет за верхнюю границу. Знак этого остатка и есть тот сигнал, по которому подстановка отличает угаданное верно от угаданного мало.

Что ломается без этого

Три ловушки. Угадать форму верно, но забыть, что константу надо ПОДОБРАТЬ, - и бросить доказательство на середине. Пропустить проверку базы - тогда «доказанное» не опирается ни на что. И самая коварная: доказывать O(n), отбрасывая по дороге лишнее +n как «младшее слагаемое», - в подстановке так нельзя, доказывать надо ровно ту форму, что угадал, до последнего слагаемого. Лишнее +n - это и есть сигнал, что догадка мала.

Зачем это в работе

Дерево быстрое, но обманчивое: легко сбиться в числе уровней или проглядеть листья. Подстановка - страховка: угадал деревом, доказал подстановкой. На практике так и делают - прикинули порядок по дереву за минуту, а если цена ошибки высока (критический алгоритм, оценка в статье), закрыли индукцией начисто. Две техники работают в паре, а не порознь.

Теперь сам

Докажи подстановкой, что T(n) = T(n/2) + 1 (двоичный поиск) это O(log n).

Ответ. Угадываем T(n) ≤ c·log₂ n. Предполагаем для n/2: T(n/2) ≤ c·log₂(n/2) = c·(log₂ n - 1). Подставляем:

T(n) = T(n/2) + 1 ≤ c·(log₂ n - 1) + 1 = c·log₂ n - c + 1 ≤ c·log₂ n при c ≥ 1

Лишнее -c + 1 ≤ 0 при c ≥ 1, неравенство замыкается - T(n) = O(log n). Базу берём при n = 2 (c·log₂ 2 = c ≥ T(2) подбором c), не при n = 1, где log₂ 1 = 0.

Главное

Подстановка доказывает оценку рекуррентности индукцией по размеру входа: угадай форму (T(n) ≤ c·n·log n), предположи её для n/2, подставь в рекуррентность и подбери c, чтобы неравенство для n замкнулось. Лишнее слагаемое, которое не уходит, - признак неверной догадки (так O(n) отвергается для 2·T(n/2)+n). База берётся не на единице, а на входе побольше, где оценка ненулевая. Дерево угадывает, подстановка доказывает.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.