这个功能有一些问题吗?
unsigned long factorial(unsigned long m)
{
return (m == 0) ? 1 : m * factorial(m - 1);
}
如果我添加其他功能:
int myCombina(int q, int p)
{
return factorial(q) / ( factorial(q) * factorial(q-p) );
}
这个myCombina()效率不高,因为应该取消最大公约数以找到组合。
max(factorial(q),factorial(q-p))可以抵消。 我们只需要计算q x(q-1)... x(q -k +1)。
还有其他问题吗?
欢迎任何评论。
由于
答案 0 :(得分:8)
如果m非常大,则可能有堆栈溢出。
堆栈溢出不是代码的主要问题...如果m非常大,在堆栈溢出之前会得到integer overflow。
如果您希望这种方法适用于大于12的m(取决于平台上unsigned long
的大小),则需要使用某种Bignum类型。
答案 1 :(得分:2)
它不是以尾递归形式编写的,所以即使编译器支持正确的尾调用优化,也不会得到好处。
答案 2 :(得分:2)
该函数实际上可能导致堆栈溢出(每个递归级别将占用堆栈的一小部分,直到它被消耗掉)。
正如其他人所提到的,你可以将递归函数转换为循环,在这种情况下可以很简单,或者你可以修改递归以允许尾调用优化(让编译器将递归转换为循环)
只是为了它,要转换为尾递归调用,函数的最后一个语句必须是一个返回,其结果来自递归调用。您的代码无法进行优化,因为您的return语句包含m*factorial(n-1)
,也就是说,您不返回递归的值,而是在返回之前对其进行操作。
使尾部递归的转换需要将乘法推送到递归调用,这通常作为保留临时结果的额外参数执行:
unsigned long factorial_tail_recursive(
unsigned long n, // number to calculate factorial
unsigned long temp_result // accumulated result
)
{
return n == 0? tmp_result
: factorial_tail_recursive( n-1, n*temp_result );
}
// syntactic sugar to offer the same interface
unsigned long factorial( unsigned long n ) {
return factorial_tail_recursive( n, 1 ); // accumulated result initialized to 1
}
但话又说回来,对于那个特定的问题,一个有效的迭代解决方案可能更容易做对。只需将累积结果保存在临时变量中并循环,直到参数减少为1。