2016-05-25 12 views
1

Как найти сложность следующего алгоритма:Как найти временную сложность рекурсивного алгоритма?

int f(int n) 
{ 
    if(n<=1) { return 1; } 
    return f(n-1) + f(n-1); 
} 

это правильно уравнение рекурсии T(n) = 2*T(N-1) + c? Как его решить?

+0

[Определение сложности для рекурсивных функций (нотация Big O)] (http://stackoverflow.com/a/13467808/1734730) выглядит связанным. –

+1

Статья в Википедии по этой теме https://en.wikipedia.org/wiki/Master_theorem – Aaron

+0

На самом деле вы можете ускорить выполнение функции 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

ответ

1

Я думаю, что ваше уравнение рекурсии верное.

Но этот конкретный случай достаточно прост, чтобы «просто подумать» об этом немного, не вдаваясь в «как решить рекурсии вообще».


Давайте посмотрим на е (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

+0

В случае сортировки слияния у нас также есть 2^N звонков? –

+0

@ivan_petrushenko Потому что у вас будет меньше уровней !!! Нарисуйте дерево для mergesort: это не одно и то же: вы перейдете от T (4) непосредственно к T (2). Вы пропустите часть T (3). Рекурсия похожа, но очень важно, чтобы ваш рекурсивный вызов работал над проблемой _half_ размера исходной проблемы, а не с меньшим количеством работы с одним элементом. – dingalapadum

+0

@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

Смежные вопросы