理论上是对数复杂度,但实际上是线性的
看一下下面的代码来找到 X^y。
/* Find exponent in logarithmic complexity */
int findPower(int base, exponent){
if( 1 == exponent ) return base;
return (findPower(base, exponent/2)*findPower(base, exponent-exponent/2));
}
int main(int argc, char *argv[]){
if(argc < 3) {
printf("Usage :: logpow baseNumber power\n");
return -1;
}
printf("%s ^ %s = %d\n", argv[1], argv[2], findPow( atoi(argv[1]),
atoi(argv[2])) );
return 0;
}
分析表明,其复杂度为 theta(log(n))。 但我运行它来测量时间,这是结果
Run 1: (calculating 1^500_million)
user-lm Programming # time ./a.out 1 500000000
1 ^ 500000000 = 1
real 0m5.009s
user 0m5.000s
sys 0m0.000s
Run 2: (calculating 1^1_Billion)
user-lm Programming # time ./a.out 1 1000000000
1 ^ 1000000000 = 1
real 0m9.667s
user 0m9.640s
sys 0m0.000s
Run 3: (calculating 1^2_Billion)
user-lm Programming # time ./a.out 1 2000000000
1 ^ 2000000000 = 1
real 0m18.649s
user 0m18.630s
sys 0m0.000s
从上面我们可以看到,实际的时间复杂度具有线性行为而不是对数!
复杂性如此巨大差异的原因可能是什么?
问候,
微内核
Have a look at the following code to find X^y.
/* Find exponent in logarithmic complexity */
int findPower(int base, exponent){
if( 1 == exponent ) return base;
return (findPower(base, exponent/2)*findPower(base, exponent-exponent/2));
}
int main(int argc, char *argv[]){
if(argc < 3) {
printf("Usage :: logpow baseNumber power\n");
return -1;
}
printf("%s ^ %s = %d\n", argv[1], argv[2], findPow( atoi(argv[1]),
atoi(argv[2])) );
return 0;
}
Analysis shows that this has a complexity of theta(log(n)).
But I ran it to measure time, and here are the results
Run 1: (calculating 1^500_million)
user-lm Programming # time ./a.out 1 500000000
1 ^ 500000000 = 1
real 0m5.009s
user 0m5.000s
sys 0m0.000s
Run 2: (calculating 1^1_Billion)
user-lm Programming # time ./a.out 1 1000000000
1 ^ 1000000000 = 1
real 0m9.667s
user 0m9.640s
sys 0m0.000s
Run 3: (calculating 1^2_Billion)
user-lm Programming # time ./a.out 1 2000000000
1 ^ 2000000000 = 1
real 0m18.649s
user 0m18.630s
sys 0m0.000s
From above we can see that the actual time complexity has linear behaviour rather than logarithmic!
What could be the reason for such a huge difference in complexity?
Regards,
Microkernel
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实际上,每次调用都会调用 2 个函数调用。递归树将是高度为
log(exponent)
的二叉树,因此其中的节点数将为2^log(exponent) == exponent
。所以总的来说它变成了一个线性算法。您可以这样重写它以获得更好的性能:技巧是,您必须存储 findPower(base, exponent/2) 的值才能获得对数复杂度。递归树仍然具有
log(exponent)
高度,但每个节点现在只有一个子节点,因此会有log(exponent)
节点。如果您实际上调用它两次,其降低性能的程度甚至会超过线性性能。如果您已经拥有相同的值,则无需第二次计算相同的值!正如 @David Schwartz 指出的,如果指数加倍,代码中的调用次数将加倍。但是,当您保存值时,将
指数
加倍只会再调用一次。You are actually invoking 2 function calls from each call. The recursion tree would be a binary tree of height
log(exponent)
, so the number of nodes in it will be2^log(exponent) == exponent
. So overall it becomes a linear algorithm. You can rewrite it like this for better performance:The trick is, you have to store the value of
findPower(base, exponent/2)
to get the logarithmic complexity. The recursion tree still has heightlog(exponent)
but each node has only one child now, so there would belog(exponent)
nodes. If you actually call it twice it will degrade the performance even more than a linear one. There's no need to calculate the same value second time if you already have that!As @David Schwartz pointed out, the number of calls made in your code would be doubled if
exponent
is doubled. But when you save the values, doubling theexponent
make only one more call.你的分析不正确,是O(N)。
当你把N从10亿增加到20亿时,你必须对10亿进行两次幂运算。因此,N 加倍会使需要完成的工作加倍。那是 O(N)。
Your analysis is incorrect, it is O(N).
When you raise N from 1 billion to 2 billion, you have to do two power operations on 1 billion. So doubling N doubles the work that needs to be done. That's O(N).
算法复杂度有一个正式的表示:
T(n) = 2T(n/2) + c
其中
n
是指数。得出T(n) = Theta(n)
分析不正确。
There is a formal representation of your algorithm complexity :
T(n) = 2T(n/2) + c
Where
n
is the exponent. Which givesT(n) = Theta(n)
The analysis is incorrect.