Один из способов найти временную сложность для перечислительных алгоритмов, подобных этому (где вы соберете все способы что-то сделать), состоит в том, чтобы подумать о том, сколько существует выходных данных и сколько времени требуется для вычисления выходных данных.
Если у вас есть n
символов, каждый из которых соответствует k
параметрам, то число возможных результатов будет k^n
.Следовательно, сложность вашего алгоритма составляет , по крайней мере, k^n
или Omega(k^n)
, поскольку перечисляются O(k^n)
выходных данных.
Нам все еще нужно рассмотреть, сколько времени требуется для вычисления каждоговход.Обратите внимание, что вы строите String
длины n
, добавляя по одному символу за раз.Поскольку String
s являются неизменяемыми, каждый раз, когда вы добавляете персонажа, должен быть создан совершенно новый String
.Работа по созданию String
длины n
путем добавления символов составляет 1 + 2 + ... + n = O(n^2)
.
К счастью, работа по созданию результата одинакова для всех результатов.Поэтому мы можем просто умножить количество результатов на работу для каждого результата, чтобы получить конечную сложность O(n^2 * k^n)
или, более конкретно, Theta(n^2 * k^n)
.
Мы также можем получить повторениеотношение следующим образом.Пусть i
будет таким же, как index
в вашем коде, что составляет от 0
до n
.Пусть j
будет n-i
, что означает «количество цифр, оставшихся для обработки».
Тогда у нас есть T(j) = k*((i+1) + T(j-1)) = k*((n-j+1) + T(j-1))
и T(0) = 1
.Общая сложность времени определяется как T(j)
, где j=n
.
Объяснение: Предположим, у вас осталось j
цифр для обработки, что соответствует одному вызову recurse
.Нам нужно перебрать k
символов, и на каждой итерации этого цикла мы выполняем i+1
работы (чтобы добавить символ к temp
), а также T(j-1)
работы (для рекурсии, имея наименьшее количество оставшихся цифр).для обработки).
Если мы "развернем" рецидив, мы найдем:
T(n) = k*(1 + T(n-1))
= k*(1 + k*(2 + T(n-2)))
= k*(1 + k*(2 + k*(3 + ... k*(n + 1)...)))
= 1*k + 2*k^2 + 3*k^3 + ... + n*k^n + 1*k^n
Затем нам нужно ограничить верхнюю и нижнюю границу этой суммы.
T(n) <= 1*k^n + 2*k^n + ... + n*k^n + 1*k^n
= (1 + 2 + ... + n)*k^n + 1*k^n
= O(n^2 * k^n)
Нижняя граница сложнее.Пусть a
будет любой константой с 0 < a < 1
.Пусть m = floor(a * n)
.
T(n) >= m*k^m + (m+1)*k^(m+1) + ... + n*k^n (there are n-m+1 terms)
>= (n-m+1) * m*k^m (replace each term with m*k^m)
= (constant*n) * (a*n)*k^(a*n)
= constant * n^2 * k^(a*n)
Это означает, что для любой константы 0 < a < 1
мы имеем T(n) = Omega(n^2 * k^(a*n))
, поэтому мы можем доказать, что наша нижняя оценка для T(n)
произвольно близка к Omega(n^2 * k^n)
.
В сочетании с верхней границей мы показали, что T(n) = Theta(n^2 * k^n)
.