a
— это «количество рекурсивных вызовов», а b
— это «на сколько частей вы разбиваете данные», что интуитивно понятно. Обратите внимание, что параметр внутри рекурсивного вызова не обязательно должен быть n
разделен на что-то, в общем случае это любая функция n
, которая описывает, как изменилась величина ваших данных.
Например, бинарный поиск выполняет один рекурсивный вызов на каждом уровне, разбивает данные на 2 и выполняет постоянную работу на каждом уровне, поэтому он имеет T(n) = T(n/2) + c
. Сортировка слиянием каждый раз разбивает данные на две части (расщепление требует работы, пропорциональной n
) и рекурсивно работает с обоими подмассивами, поэтому вы получаете T(n) = 2T(n/2) + cn
.
В вашем примере у вас будет T(n) = T(n-1) + c
, поскольку вы делаете один рекурсивный вызов и «разделяете данные», каждый раз уменьшая их размер на 1.
Чтобы получить из этого нотацию большого O, вы просто делаете замены или расширяете. На вашем примере это легко:
T(n) = T(n-1) + c = T(n-2) + 2c = T(n-3) + 3c = ... = T(0) + nc
Если принять T(0) = c0
, некоторую «базовую константу», то получится T(n) = nc + c0
, что означает, что проделанная работа находится в O(n)
.
Пример с бинарным поиском аналогичен, но вы должны сделать замену — попробуйте разрешить n = 2^m
и посмотрите, что вы можете с этим сделать. Наконец, вывод большого обозначения O, например. T(n) = T(sqrt(n)) + c
действительно классное упражнение.
Изменить. Существуют и другие способы решения рекуррентных отношений. Стандартным методом является Основная теорема. Но доказательство не очень хорошее, и описанный выше метод работает для каждого повторения, к которому я когда-либо применял его. И... ну, это просто веселее, чем подставлять значения в формулу.
person
hnefatl
schedule
21.07.2017