Как найти сложность следующего алгоритма:Как найти временную сложность рекурсивного алгоритма?
int f(int n)
{
if(n<=1) { return 1; }
return f(n-1) + f(n-1);
}
это правильно уравнение рекурсии T(n) = 2*T(N-1) + c
? Как его решить?
Как найти сложность следующего алгоритма:Как найти временную сложность рекурсивного алгоритма?
int f(int n)
{
if(n<=1) { return 1; }
return f(n-1) + f(n-1);
}
это правильно уравнение рекурсии T(n) = 2*T(N-1) + c
? Как его решить?
Я думаю, что ваше уравнение рекурсии верное.
Но этот конкретный случай достаточно прост, чтобы «просто подумать» об этом немного, не вдаваясь в «как решить рекурсии вообще».
Давайте посмотрим на е (3)
f(3)
f(2) + f(2)
f(1) + f(1) + f(1) + f(1)
Итак, сколько звонков мы имеем? 1 + 2 + 4
Хмм .. как насчет f (4)?
f(4)
f(3) + f(3)
f(2) + f(2) + f(2) + f(2)
f(1) + f(1) + f(1) + f(1) + f(1) + f(1) + f(1) + f(1)
Итак, сколько звонков у нас есть? 1 + 2 + 4 + 8
Таким образом, мы можем сделать обоснованное предположение для n = 5: 1 + 2 + 4 + 8 + 16. И если вы думаете об этом, это также имеет смысл, потому что: numCalls (f (5)) = 2 * numCalls (f (4)) + 1 (+ 1 происходит от вызова до самого f (5)).
Мы можем обобщить это
T(n) = sum(2^i) for i in (0, n-1)
Теперь, если мы используем тот факт, что
sum(2^i) for i in (0, n-1) == 2^n - 1
это становится совершенно очевидно, что
T(n) = 2^n - 1
, который находится в O(2^n)
в качестве упражнения:
Докажите по индукции, что
T(n) = 2*T(n-1) + 1 <=> T(n) = 2^n - 1
Или немного больше общего:
T(n) = 2*T(n-1) + c <=> T(n) = c*(2^n - 1)
Подобно тому, как побочного сведению, как предложено в комментарии: вы можете значительно улучшить производительность, используя memoization
В случае сортировки слияния у нас также есть 2^N звонков? –
@ivan_petrushenko Потому что у вас будет меньше уровней !!! Нарисуйте дерево для mergesort: это не одно и то же: вы перейдете от T (4) непосредственно к T (2). Вы пропустите часть T (3). Рекурсия похожа, но очень важно, чтобы ваш рекурсивный вызов работал над проблемой _half_ размера исходной проблемы, а не с меньшим количеством работы с одним элементом. – dingalapadum
@ivan_petrushenko В mergesort вы получите дерево рекурсии с уровнями log (n). Здесь вы получаете дерево рекурсии с n уровнями! Вот почему вы получаете совсем другие результаты. Подумайте о T (8). Здесь вы поедете T (8), T (7), T (6), T (5), T (4), T (3), T (2), T (1). В mergesort вы пойдете T (8), T (4), T (2), T (1). Это становится еще яснее, если вы посмотрите на большие числа – dingalapadum
[Определение сложности для рекурсивных функций (нотация Big O)] (http://stackoverflow.com/a/13467808/1734730) выглядит связанным. –
Статья в Википедии по этой теме https://en.wikipedia.org/wiki/Master_theorem – Aaron
На самом деле вы можете ускорить выполнение функции memo f (n) 'int memo [N]; int f (int n) { if (n <= 1) {return 1; } f [n] = f (n - 1); return f [n] << 1; } ' – kaitian521