我正在通过项目Euler,我遇到了一个组合问题。组合逻辑意味着计算阶乘。所以,我决定创建一个阶乘方法。然后我遇到了一个问题 - 因为我可以很容易地使用迭代和递归来做这个,我应该去哪一个?我很快写了两个方法 - 迭代:
public static long factorial(int num) {
long result = 1;
if(num == 0) {
return 1;
}
else {
for(int i = 2; i <= num; i++) {
result *= i;
}
return result;
}
和递归:
public static long factorial(int num) {
if(num == 0) {
return 1;
}
else {
return num * factorial(num - 1);
}
}
如果我(显然)在这里谈论速度和功能,我应该使用哪一个?而且,一般来说,这种技术通常比其他技术更好(所以如果我以后遇到这个选择,我应该去做什么)?
答案 0 :(得分:13)
两者都是绝望的天真。没有认真应用factorial会使用任何一个。我认为对于大n来说两者都是低效的,当参数很大时,int
和long
都不够。
更好的方法是使用良好的gamma function实施和记忆。
Here's Robert Sedgewick的实施。
大值将需要对数。
答案 1 :(得分:0)
每当你得到一个在递归和迭代之间选择的选项时,总是去迭代,因为
1.Recursion涉及创建和销毁堆栈帧,这需要很高的成本。
2.如果你使用的是非常大的值,你的筹码可能会爆炸。
所以只有在你有一些非常诱人的理由时才去递归。
答案 2 :(得分:0)
对于这个问题,没有“这更好,更糟糕”。因为现代计算机非常强大,所以在Java中,它往往是你个人喜欢的。您正在迭代版本中执行更多检查和计算,但是您在递归版本中将更多方法堆积到堆栈中。每个人的利弊,所以你必须逐个采取。
就个人而言,我坚持使用迭代算法来避免递归逻辑。
答案 3 :(得分:0)
我实际上是按时间因素分析这个问题。 我做了2个简单的实现:
迭代:
private static BigInteger bigIterativeFactorial(int x) {
BigInteger result = BigInteger.ONE;
for (int i = x; i > 0; i--)
result = result.multiply(BigInteger.valueOf(i));
return result;
}
和递归:
public static BigInteger bigRecursiveFactorial(int x) {
if (x == 0)
return BigInteger.ONE;
else
return bigRecursiveFactorial(x - 1).multiply(BigInteger.valueOf(x));
}
测试两个都在单线程上运行。 事实证明,Iterative仅在使用小参数时稍快一些。当我把n大于100的递归解决方案更快。 我的结论?你永远不能说迭代解决方案比JVM上的递归更快。 (仍然只谈时间)
如果您有兴趣,我会得到这个结论HERE
如果您对更深入了解这两种方法之间的差异感兴趣,我在knowledge-cess.com
上找到了非常好的描述