这是迭代版本,但它调用递归函数。这会对其时间/空间复杂性产生影响吗?
int factorial(int n) {
if (n == 1) {
return 1;
}
else {
return n * factorial(n - 1);
}
}
int binomial_coefficient_iterative(unsigned int n, unsigned int k) {
if (k == 0 || k == n) {
return 1;
}
else {
return (factorial(n) / ( factorial(k) * factorial(n - k) ) );
}
}
这是递归版本,使用C(n,k)= C(n-1,k)+ C(n-1,k-1)公式计算。
int binomial_coefficient_recursive(unsigned int n, unsigned int k){
if (k == 0 || k == n) {
return 1;
}
else {
return binomial_coefficient_recursive(n - 1, k) + binomial_coefficient_recursive(n - 1, k - 1);
}
}
最后但并非最不重要的是,你能用C(n,k-1)计算二项式系数C(n,k)吗?
答案 0 :(得分:1)
解决方案都取决于递归。在第一个版本中,您可以使用简单迭代替换factorial的递归调用。
但是,在第二个解决方案中存在重新计算重叠子问题的问题。
C(n, k) = C(n-1, k) + C(n-1, k-1)
你应该使用memoization来缓存C(n,k)的值,只要它被计算存储值,当函数调用相同的参数时,重新计算,查找并返回值。
在第一个问题中,您正在多次调用阶乘函数,这是可以避免的。策略是计算增量变化。例如,当您计算factorial(k)
时,您可以派生
factorial(n) = factorial(k) * K+1 * K+2 ...n
这减少了你正在进行的乘法次数。
回到问题的时空复杂性。
第一:时间复杂度是O(n),这里是3个阶乘调用,你正在做n,k和n-k乘法
第二:它将是
T(n,k) = T(n-1,k) + T(n-1,k-1) + O(1)
where T(n,n) = T(n,0) = O(1)
求解这个差分方程,你会得到T(n)= O(2 ^ n),(用于寻找斐波那契数列复杂度的相同参数)
所以后面的方法是指数的,可以使用memoization来降低。