【问题标题】:What is the Big O of a For Loop, Iterated Square Root Times?For循环的大O,迭代平方根时间是多少?
【发布时间】:2014-02-19 03:27:28
【问题描述】:

我正在尝试为这个代码片段找到大 O:

for (j = 0; j < Math.pow(n,0.5); j++ ) {
 /* some constant operations */
}

由于循环运行了 √n 次,我假设这个 for 循环是 O(√n)。但是,我在网上看到 √n = O(logn)。

那么这个 for 循环是 O(√n) 还是 O(logn)?

谢谢!

【问题讨论】:

  • √n = O(logn) 只是愚蠢的。你在哪里读到的?显然循环将运行O(sqrt(n)) 次。
  • 你在哪里读到 √n = O(logn)?当然,O(√n) != O(logn) 因为 √n != log(n)。也许这意味着计算 √n 的某个算法是 O(logn)
  • 请提供 O(√n)=O(logn) 的链接。实际上,对于大 n,O(√n) > O(logn)。
  • 所以这个for循环只有O(√n)?
  • 是的,假设j - 0是一个错字(应该是j = 0

标签: java algorithm big-o computer-science


【解决方案1】:

必须做出几个假设,但这个循环的时间复杂度似乎是 O(√n)。假设是:

  • 无论j 的值如何,循环体都会在恒定时间内执行。
  • j 在循环体中没有被修改
  • n 在循环体中没有被修改
  • Math.pow(n,0.5) 以恒定时间执行(可能是真的,但取决于具体的 Java 执行环境)

正如评论所指出的,这还假设循环初始化是 j = 0 而不是 j - 0

请注意,如果重写循环,效率会更高:

double limit = Math.pow(n, 0.5);
for (j = 0; j < limit; j++ ) {
 /* some constant operations */
}

(只有在主体没有改变n时,这才是有效的重构。)

【讨论】:

  • Java不能自己做这种优化吗?!
  • 如果n 是局部变量,我希望它至少可以优化这一点,但也许我错了。
  • @NiklasB。 - 它询问了很多编译器。它不仅必须能够确定n 没有更改值(声明它final 会有所帮助),而且编译器还必须知道Math.pow(n,0.5) 每次调用它时返回相同的值相同的论点。我不认为编译器对整个标准 API 有这么详细的模型。
  • 是的,如果循环说 j * j &lt; n 而不是 j &lt; Math.pow(n, 0.5),一切都会更好。让整数为整数,浮点数为浮点数。
  • @David: j * j 每次迭代都会产生整数乘法;除了小的 n 之外,一次计算整数平方根是有利的(不幸的是,它不可用,必须通过浮点 sqrt 来模拟)。跨度>
【解决方案2】:

假设对于某个函数Ppow 操作的成本为O(P(n)),则循环的全局成本为O(√n.P(n))。如果将pow 调用从循环中取出并只执行一次,则成本表示为O(√n+P(n))

如果是P(n)=1,则分别给出O(√n)O(√n)

如果是P(n)=log(n),这将给出O(√n.log(n))O(√n)

[和的低阶项被另一个吸收。]

假设P(n)=log(n) 在任意精度整数的上下文中可能是有效的,其中整数n 的表示至少需要O(log(n)) 位。但这仅适用于 n 的巨大值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2023-03-11
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2016-06-20
    相关资源
    最近更新 更多