#go #big-o
#Вперед #большой-о
Вопрос:
У меня есть этот код для вычисления мощности определенного числа
func power(x, n int) int {
if n == 0 {
return 1
}
if n == 1 {
return x
}
if n%2 == 0 {
return power(x, n/2) * power(x, n/2)
} else {
return power(x, n/2) * power(x, n/2) * x
}
}
Итак, общее количество выполнений равно 1 2 4 … 2^ к
и в соответствии с формулой геометрической прогрессии
a(1-r ^ n) / (1-r)
сумма времени выполнения будет равна 2 ^ k, где k — высота двоичного дерева
Следовательно, временная сложность равна 2 ^ logn
Я прав? Спасибо 🙂
Комментарии:
1. По-видимому, ваша формула для суммирования геометрических рядов неверна (когда r> 1). Коэффициент должен быть (r ^ n — 1) и (r — 1) [ни (1 — r ^ n), ни (1 — r)].
2. @ShudiptaSharma о, но я ссылался на эту формулу из вики: en.wikipedia.org/wiki/Geometric_progression
Ответ №1:
ДА.
Другой способ мышления о сложности рекурсивных функций — (количество вызовов) ** (высота рекурсивного дерева)
При каждом вызове вы выполняете два вызова, которые делят n на два, поэтому высота дерева равна logn, поэтому временная сложность равна 2 ** (logn), что равно O (n)
Смотрите Здесь Гораздо более формальное доказательство:
https://cs.stackexchange.com/questions/69539/time-complexity-of-recursive-power-code
Комментарии:
1. Если вы присмотритесь, то обнаружите, что fn не выполняет 2 вызова одновременно. Каждый раз, когда он проходит через блок if-else. Это означает либо n%2 == 0, либо n%2 == 1, а не оба. Правильно. Таким образом, вы не можете просто рассматривать это как 2 дочерних вызова.
2. @ShudiptaSharma Но если вы посмотрите еще внимательнее, в обоих случаях есть два вызова:
return power(x, n/2) * power(x, n/2)
илиreturn power(x, n/2) * power(x, n/2) * x
3. О, да, я это признаю. Я не заметил, что это происходит дважды с использованием оператора *. Приношу извинения за мои действия и восстанавливаю вашу репутацию.
Ответ №2:
Каждый раз, когда вы делите n на 2, если n <= 1. Итак, подумайте, сколько раз вы можете уменьшить n до 1 только путем деления на 0? Давайте посмотрим,
n = 26 n1 = 13 n2 = 6 (возьмите этаж 13/2) n3 = 3 n4 = 1 (возьмите этаж 3/2)
Допустим, x_th степень 2 больше или равна x. Затем,
2^x >= n
or, log2(2^x) = log2(n)
or, x = log2(n)
Именно так вы находите временную сложность вашего алгоритма как log2 (n).
Комментарии:
1. Нет, вы просто приняли во внимание количество вызовов, пока n не станет 1, что действительно равно log2 (n) . Но вам также необходимо учитывать количество вызовов в каждом вызове, которое равно 2, поэтому временная сложность равна O (n)