2015-11-23 6 views
2

Является ли большой (O) следующий рекурсивный код просто O (n выбирает k)?Большой (O) рекурсивный n выбирает k код

int nchoosek(int n, int k) { 
    if (n == k) return 1; 
    if (k == 0) return 1; 
    return nchoosek(n-1, k) + nchoosek(n-1, k-1); 
} 
+0

ли вы нарисовать дерево? – erip

+1

Код очень похож на код последовательности Фибоначчи, поэтому я оставлю [это] (http://stackoverflow.com/questions/360748/computational-complexity-of-fibonacci-sequence/360773#360773) здесь. – erip

+0

@erip Используя дерево, я понял, что он может быть 2^n, но из математических вычислений, чтобы получить nchoosek, он, кажется, ограничен n! вместо – cppgnlearner

ответ

1

Я не уверен, если запись является правильным, но я думаю, вы можете написать повторения для этой функции, как

T(n) = T(n-1, k) + T(n-1, k-1) + O(1) 

Поскольку у вас есть два возможных пути мы просто должны проанализировать худший случай каждого и выбрать самый медленный.

Худший случай T(n-1, k)

Учитывая, что 0<k<n и k находится как можно дальше от n то мы имеем

T(n-1, k) = T(n-1) = O(n) 

Худший случай T(n-1, k-1)

Нам нужно 0<k<n и k shoul d как можно ближе к n. Тогда

T(n-1, k-1) = T(n-1) = O(n) 

Поэтому T(n, k) = 2*O(n) + O(1) = O(n)

Другой способ увидеть это за счет уменьшения проблемы с другими известными проблемами, например, вы можете решить ту же проблему, используя определение функции выбора в терминах Факториал функция:

nCk = n!/k!(n-k)! 

Хронометраж факторного является O(n) даже в рекурсивном случае.

nCk требует вычисление факториала три раза:

n! => O(n) 
k! => O(k) = O(n) 
(n-k)! => O(n-k) = O(n) 

Тогда умножение и деление как постоянное время O(1), следовательно, время работы является:

T(n) = 3*O(n) + 2*O(1) = O(n) 
Смежные вопросы