Шаг 52.
Рекурсия на Python. Анализ времени выполнения рекурсивных алгоритмов. Рекуррентные соотношения. Метод расширения. Основная теорема
На этом шаге мы рассмотрим эту теорему.
Основная теорема (master theorem) может использоваться в качестве быстрого способа определения временнОй сложности вычисления алгоритмов, основанных на стратегии "разделяй и властвуй".
В частности, её можно применить к рекуррентным соотношениям следующего вида:
c, если n = 1
T(n) =
aT(n/b) + f (n), если n > 1,
где
a ≥ 1, b > 1, c ≥ 0 и
f() - асимптотически положительная функция. Подобные алгоритмы обычно относятся к тем задачам, исходный размер которых делится на некоторое
положительное число
b, не меньшее двух. Последующая обработка или объединение решений подзадач требуют
f(n) операций. В зависимости от вклада слагаемых
aT(n/b) и
f(n) в стоимость выполнения алгоритма основная теорема в её самой общей форме утверждает, что можно определить асимптотическую жёсткую границу для
T в следующих трех случаях:
- Если f(n) = Ο(nlogba-ε) для некоторой константы ε > 0, то T(n) ∈ Θ(nlogba);
- Если f(n) = Θ(nlogba (log n)k), где k ≥ 0, то T(n) ∈ Θ(nlogba (log n)k+1);
- Если f(n) = Ω(nlogba+ε), где ε > 0 и f(n) удовлетворяет так называемому условию регулярности
a * f(n/b) ≤ d * f(n) для некоторой константы d < 1 и для всех достаточно больших n, то T(n) ∈ Θ(f(n)).
Например, для
1, если n = 1
T(n) =
T(n/2) + 2n, если n > 1
можно найти такое
ε > 0, что порядок
f(n) = 2n будет больше
n(log21)+ε = nε. Действительно,
в этом примере допустимо любое значение
ε > 0, поскольку порядок показательной функции
2n всегда выше порядка полиномиальной. Таким образом, это
рекуррентное соотношение относится к третьему случаю основной теоремы, который подразумевает, что
T(n) ∈ Θ(2n).
Если f(n) - полином степени k, то можно воспользоваться следующей более простой версией основной теоремы:
Θ(nk), если a * bk < 1
T(n) ∈ Θ(nk log n), если a * bk = 1 (3.28)
Θ(n logb a), если a * bk > 1
Этот результат может быть получен методом расширения. Рассмотрим следующее рекуррентное соотношение:
c, если n = 1
T(n) = (3.29)
aT(n/b) + d * nk, если n > 1
где
a ≥ 1, b > 1, c ≥ 0 и
d ≥ 0.
Процесс его расширения:
T(n) = aT(n/b) + dnk = a[aT(n/b2) + d(n/b)k] + dnk =
= a2T(n/b2) + dnk(1 + a/bk) = a2[aT(n/b3) + d(n/b2)k] + dnk(1 + a/bk) =
= a3T(n/b3) + dnk(1 + a/bk + a2/b2k) =
. . . .
i-1
= aiT(n/bi) + dnk ∑ (a / bk)j.
j=1
Начальное условие T(1) = c достигается при i = logb n, а подстановка этого значения в формулу даёт:
logbn-1 logbn-1
T(n) = c * alogbn + d * nk ∑ (a / bk)j = c * nlogba + d * nk ∑ (a / bk)j ,
j=0 j=0
где в зависимости от значений
a, b и
k возможны три случая.
- Если a < bk, то
будет постоянной величиной (которая не может быть бесконечностью). Отметим, что бесконечная сумма
∞
∑ ri = 1 / (r - 1) -
i=0
константа при r < 1 (то есть не расходится).
Таким образом, в этом случае
для некоторой постоянной K. Кроме того, поскольку a < bk, то есть logb a < k, то nk - член высшего порядка. Следовательно:
- Если a = bk, то
logbn-1
T(n) = c * nk + d * nk ∑ 1 = c * nk + d * nk logb n ,
j=0
из чего следует, что
- Если a > bk, то, вычислив сумму геометрической прогрессии, получим:
T(n) = c * nlogba + dnk((a/bk)logbn - 1))/(a/bk - 1) =
= c * nlogba + dnk(nlogba/nk - 1) K =
= (c + dK) nlogba - dKnk,
где K = 1/(a/bk - 1) - константа. Наконец, поскольку a > bk , то есть logb a > k, мы имеем:
На следующем шаге мы рассмотрим дополнительные примеры.
Предыдущий шаг
Содержание
Следующий шаг