Давайте посчитаем только умножения в вызове pow
, обозначенного как M(N)
, предполагая, что они преобладают в стоимости (в настоящее время совершенно неверное предположение).
Изучив код, мы видим, что:
M(0) = 0
(без умножения для N=0)
M(1) = 0
(без умножения для N=1)
M(N)
, N>1, N четное = M(N/2) + 1
(для четного N рекурсивный вызов после одного умножения)
M(N)
, N>1, N нечетное = M(N/2) + 2
(для нечетного N рекурсивный вызов после одного умножения, за которым следует второе умножение).
Это повторение немного усложняется тем, что оно по-разному обрабатывает четные и нечетные целые числа. Мы обойдем это, рассматривая последовательности только четных или нечетных чисел.
Давайте сначала рассмотрим случай, когда N
является степенью числа 2. Если мы повторим формулу, мы получим M(N) = M(N/2) + 1 = M(N/4) + 2 = M(N/8) + 3 = M(N/16) + 4
. Мы легко обнаруживаем шаблон M(N) = M(N/2^k) + k
, так что следует решение M(2^n) = n
. Мы можем записать это как M(N) = Lg(N)
(логарифм по основанию 2).
Точно так же N = 2^n-1
всегда будет давать нечетные числа после деления на 2. У нас есть M(2^n-1) = M(2^(n-1)-1) + 2 = M(2^(n-2)-1) + 4... = 2(n-1)
. Или M(N) = 2 Lg(N+1) - 2
.
Точное решение для общего N
может быть довольно сложным, но мы видим, что Lg(N) <= M(N) <= 2 Lg(N+1) - 2
. Таким образом, M(N)
равно O(Log(N))
.
person
Yves Daoust
schedule
29.01.2014