如何解决哪个递归调用最有效?
因此,我的任务是编写一种借助递归来查找x的n次幂的方法。基本情况是,如果n = 0,则x ^ n = 1。 如果n是一个奇数,则x ^ n = x *(x ^ 2)^((n-1)/ 2)。 如果n是偶数,则x ^ n =(x ^ 2)^(n / 2)。不知道您是否需要此信息,只是为了以防万一添加。
我的问题是我有两种使用递归调用的方法,但是我不确定哪种是“最好的”或效率最高的。
这是方法:
public double findNthPowerOfXV2(int n,double x){
if(n == 0){
return 1;
}else if(!(n % 2 == 0)){
return x * findNthPowerOfXV2(((n-1)/2),x) * findNthPowerOfXV2(((n-1)/2),x);
//return x * findNthPowerOfXV2(((n-1)/2),x * x) also works,but not sure which is best
}else{
return findNthPowerOfXV2(n/2,x) * findNthPowerOfXV2(n/2,x);
//return findNthPowerOfXV2(n/2,but not sure which is best
}
}
对我来说,被注释掉的代码行看起来更好,更正确。当我说注释掉的行使该方法执行更少的循环时,我不确定是否错误。 但是,当我测试完成该方法所花费的时间时,未注释掉的行比正在注释的行要快。即使它有两个递归调用,我猜这会导致更多的循环吗?
这是我用来测试方法使用时间的代码:
Date start2 = new Date();
int rounds2 = 0;
double time2;
Date stop2;
do {
main.findNthPowerOfXV2(5000,1.001);
stop2 = new Date();
++rounds2;
}while(stop2.getTime() - start2.getTime() < 1000);
time2 = (double) stop2.getTime() - start2.getTime() / rounds2;
System.out.println(time2);
当我使用未注释掉的行时,我得到1.597890920672E12
使用注释掉的行时,我得到1.597915039728E12
那么哪个更适合使用?我正在寻找一种解释,哪种解释更好,为什么使用。在此先感谢:)
解决方法
您是正确的,原则上讲,注释掉的版本效率更高。例如,在计算2^4
时,请考虑我们进行了多少次呼叫。
首先是低效版本:
- 2^4
- 2^2
- 2^1
- 2^0
- 2^0
- 2^1
- 2^0
- 2^0
- 2^2
- 2^1
- 2^0
- 2^0
- 2^1
- 2^0
- 2^0
如果我们将n
加倍,则此树的大小将加倍,因此该算法为O(n)
。另一种看待这种情况的方法是假设对递归调用是正确的,然后证明对基本调用也正确。在这种情况下,我们要进行两个递归调用,每个递归调用都执行n/2
操作(假设),因此基本调用执行2 * n/2 = n
操作。
现在是高效版本:
- 2^4
- 2^2
- 2^1
- 2^0
在这里,如果我们将n
的值 double 加倍,则树的大小将增加1,因此,这就是O(log n)
。
我将把严格的证据留给读者。在这两种情况下,我都忽略了n
的奇数值,因为它们在big-O方案中无关紧要。
您无法衡量这种差异的事实可能表明您的基准测试代码更多:
-
构造一个
new Date
对象将调用内存管理器,可能会触发垃圾回收器,并可能执行系统调用以从操作系统中获取当前时间,因此它可能比实际花费的时间更长。您正在测试的功能。 -
Java运行时(我假设这是Java)使用即时编译器,该编译器仅在多次调用函数时才启动,因此第一次运行时,结果不具有代表性。 / p>
-
也许编译器很聪明,可以识别出该函数是纯函数,并且您正在使用相同的参数进行两次调用,因此它的效率可能不如看上去的低。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。