代码时间复杂度分析
int foo(int n)
{
int x=2;
while (x<n)
{
x = x*x*x;
}
return x;
}
我需要分析一下它的时间复杂度。我注意到它达到 n
的速度比 log(n)
快得多。我的意思是,它执行的步骤比 O(log(n)) 执行的步骤少。我读了答案,但不知道他们是如何得到它的:它是O(log(log(n))
。现在,你如何处理这样的问题?
int foo(int n)
{
int x=2;
while (x<n)
{
x = x*x*x;
}
return x;
}
I need to analyze its time complexity. I noticed it reaches n
much faster than just log(n)
. I mean, it does less steps than O(log(n))
would do. I read the answer but have no idea how they got to it: It is O(log(log(n))
. Now, how do you approach such a question?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
把它想象成一个递归函数:
如果你展开它:
函数随着幂的幂而增长...所以达到某个数字(即计算函数的逆)的时间(迭代)是对数对数。
正如您的示例中的
f(0) = 2
,我们想知道f(i) >= n
何时成为n
输入参数(以及i
迭代次数):因此,要达到
n
值,需要log_3(log_2(n))
次迭代(round处理整数时要超过它)。如果函数是:
那么模式是:
在这种情况下,函数的倒数将以 2 为底的单个对数。
我的数学不是很严格,但我希望你能明白这个想法。
think of it as a recursive function:
if you expand it:
the function grows as the power of the power... so the time (iterations) to reach a certain number (that is, calculating the inverse of the function) is the logarithm of the logarithm.
As in your example
f(0) = 2
, we want to know whenf(i) >= n
beingn
the input parameter (andi
the number of iterations):So to reach a value of
n
, ittakes log_3(log_2(n))
iterations (round up while dealing with integers to surpass it).if the function would be:
then the pattern would be:
And in this case, then the inverse of the function would be a single logarithm in base 2.
My math is not very rigorous, but I hope you'll get the idea.
考虑 x 如何随着循环迭代次数的变化而变化。每一次,你都会把它切成立方体。因此,经过 i 次迭代后,该值将是 2 的立方,再次立方......依此类推,i 次。我们用 x(i) 来表示这个表达式。假设 x(0)=2、x(1)=23 等(我使用 ab 表示 a 的 b 次幂)。
当 x(i)>=n 时我们就完成了。多久时间?让我们来解决 i.
我们可以忽略常数因素,我们得出的结论是我们将采取 log(log(n)) 步骤。这就是你的算法的复杂性。
希望像这样分解所有步骤会有所帮助。
Think about how x changes with the number of iterations through the loop. Each time, you cube it. So after i iterations, the value will be 2 cubed, cubed again... and so on, i times. Let's use x(i) to denote this expression. Let's say x(0)=2, x(1)=23, etc (I'm using ab to mean a raised to the bth power).
We're done when x(i)>=n. How long does it take? Let's solve for i.
We can ignore the constant factors, and we're left with the conclusion that we'll take log(log(n)) steps. That's the complexity of your algorithm.
Hopefully, breaking down all the steps like that helps.
让
L3 = 对数以 3 为底
L2 = 对数到底数 2
那么正确答案是 O(L3(L2(n)) 而不是 O(L2(L2(n))。
从 < strong>x = x * 2,x 将呈指数增长,直到达到 n,从而使时间复杂度为 O(L2(n))
现在考虑 x = x * x。在每次迭代中,x 的值都会跳到其前一个值的平方,我们得到的结果如下:
对于 x = 2。
n = 4,迭代次数 = 1
n = 16,迭代次数 = 2
n = 256,迭代次数 = 3
n = 65536,迭代次数 = 4
因此,时间复杂度为 O(L2(L2(n))。您可以通过将值置于 n 的值之上来验证这一点。
现在来解决您的问题,< strong>x = x * x * x 这会比 x = x * x 增长得更快,如下表:
对于 x = 2。
n = 8,迭代次数 = 1
n = 512,迭代次数 = 2
n = (512*512*512),迭代次数 = 3 等等
如果仔细观察,结果是 O(L3(L2(n))。L2(n)会得到 2 的幂,但是由于您在每次迭代中都取 x 的立方,因此您必须以 3 为底取对数才能找出正确的迭代次数,
所以我认为正确的答案是 <。 strong>O(log-to-base-3(log-to-base-2(n))
概括这一点,如果x = x * x * x * x * ..(k 次) ,那么时间复杂度为O(log-to-base-k(log-to-base-2(n)
Let
L3 = log to the base 3
L2 = Log to the base 2
Then the correct answer is O(L3(L2(n)) and NOT O(L2(L2(n)).
Start with x = x * 2. x will increase exponentially till it reaches n, thus making the time complexity O(L2(n))
Now consider x = x * x. x increases faster than the above. In every iteration the value of x jumps to the square of its previous value. Doing some simple math, here is what we get:
For x = 2
n = 4, iterations taken = 1
n = 16, iterations taken = 2
n = 256, iterations taken = 3
n = 65536, iterations taken = 4
Thus, the time complexity is O(L2(L2(n)). You can verify this by putting values above values for n.
Now coming to your problem, x = x * x * x. This will increase even faster than x = x * x. Here is the table:
For x = 2
n = 8, iterations taken = 1
n = 512, iterations taken = 2
n = (512*512*512), iterations taken = 3 and so on
If you look at this carefully, this turns out to be O(L3(L2(n)). L2(n) will get you the power of two, but since you are taking cube of x in every iteration, you will have to take log to the base 3 of it to find out the correct number of iteration taken.
So I think the correct answer is O(log-to-base-3(log-to-base-2(n))
Generalizing this, if x = x * x * x * x * .. (k times), then the time complexity is O(log-to-base-k(log-to-base-2(n)
如果 while 循环内的代码是
x,则在 O(log(n)) 次迭代中将达到 n。由于您对 x 进行立方而不是仅将其乘以常数,因此您将更快地达到 n。
If the code inside the while loop were
x would reach n in O(log(n)) iterations. Since you're cubing x instead of just multiplying it by a constant, you'll reach n faster.
鉴于
此,
该函数将比您的函数快或慢多少(通过循环迭代次数来衡量)?
这个函数比你的函数快或慢多少?
但此函数仅将
log_log_x
增加一个常量,因此很容易计算出它执行了多少次迭代。Given
So
How much faster or slower ( measured by number of iterations of the loop ) will this function be than your function?
And how much faster or slower will this function be than your function?
But this function only increments
log_log_x
by a constant, so it's easy to work out how many iterations it does.设
i
为迭代步数,x(i)
为i
步后x
的值。我们有总步数是最大的
i
,因此x(i)
x(i) < n
。我们有
对数严格递增,所以
Let
i
be the number of iteration steps andx(i)
the value ofx
afteri
steps. We haveThe total number of steps is the biggest
i
so thatx(i) < n
.We have
The logarithm is strictly increasing, so
为什么不添加一个计数器变量来计算循环的迭代次数。在函数返回之前将其打印出来。
然后针对一系列值调用该函数,例如从 3 到 1,000,000 开始。然后使用 GNUPlot 之类的内容绘制结果。
然后查看该图是否与已知曲线匹配。
Why not add a counter variable to count the number of iterations of the loop. Print it out just before the function returns.
Then call the function for a range of values, e.g. 3 to 1,000,000 to start with. Then plot your result using something like GNUPlot.
Then see if the graph matches a known curve.