【问题标题】:Worst case time complexity of Math.sqrt in javajava中Math.sqrt的最坏情况时间复杂度
【发布时间】:2016-06-02 03:12:55
【问题描述】:

我们有一个测试练习,您需要找出给定的 N 数是否是另一个数的平方,是否具有最小的时间复杂度。

我写道:

public static boolean what2(int n) {
    double newN = (double)n;
    double x = Math.sqrt(newN);
    int y = (int)x;
    if (y * y == n)
        return false;
    else
        return true;
}

我在网上查看,特别是在 SO 上试图找到 sqrt 的复杂性,但找不到。 This SO post 用于 C#,表示其 O(1),this Java post 表示其 O(1),但可能会遍历所有双精度数。

我试图了解这种方法的最差时间复杂度。所有其他操作都是 O(1),所以这是唯一的因素。 希望有任何反馈!

【问题讨论】:

  • 你为什么不用log
  • 不确定这对您来说是否显而易见,但此函数不回答所提出的问题 - 它只回答数字是正方形。
  • 如果数字是正方形,它应该返回 false,如果不是 @ThomasAndrews,它应该返回 true
  • 这肯定不能在少于 O(log N) 的时间内完成,因为每一位都是相关的,所以你必须阅读每一位 log N 位。
  • 另外,请注意int y=(int) x; 不会四舍五入,因此如果平方根函数的错误返回 202.999999999,那么您将测试错误的值。您需要使用实际的舍入函数,或使用(int)(x+0.5);

标签: java math time-complexity math.sqrt


【解决方案1】:

使用浮点转换没问题,因为java的int类型是32位,而java的double类型是IEEE 64位格式,可以精确表示所有32位整数的值。

如果您要为long 实现函数,则需要更加小心,因为许多大的long 值并不能完全表示为doubles,因此取平方根并将其转换为整数type 可能不会产生 实际 平方根。

您实现中的所有操作都在恒定时间内执行,因此您的解决方案的复杂性确实是 O(1)

【讨论】:

  • 那么 Math.sqrt(n) 呢?那不应该是O(n)吗?
  • Math.sqrt(n) 是用一种比 O(n) 更高效的方法实现的。与其他代码相比,尤其是解释器开销,可以假设它在恒定时间内执行。
【解决方案2】:

如果我正确理解了这个问题,Java 指令可以通过即时编译转换为使用本机 fsqrt 指令(但我不知道这是否真的如此),根据到this table,使用有限数量的处理器周期,这意味着复杂度将是O(1)

【讨论】:

  • 不幸的是,我们不允许使用“标准”方法之外的任何东西,所以只有 Math 和标准 serach 方法。实际上大多数人都是用二分搜索来做的,但对我来说似乎有点愚蠢,我希望 sqrt 能够实现二分搜索(如果不是更好的话)
【解决方案3】:

java 的 Math.sqrt 实际上将 sqrt 委托给 StrictMath.java 源代码可以找到其实现之一here,通过查看 sqrt 函数,看起来复杂度是常数时间。看看里面的 while(r != 0) 循环。

【讨论】:

  • 最糟糕的是什么?
  • 看实际代码,反正Oracle的java也没有用到,Math.sqrt的复杂度是O(1)。它循环了 52 次:这不是 Log(N),这是恒定时间,比使用浮点操作码效率低得多,但仍然是恒定时间。
  • @chqrlie 谢谢。是的,当使用 0x0020000000000000L 初始化时,while ( r != 0 ) 在 52 中循环,这是恒定时间。你能告诉我为什么 Oracle 的 java 不使用这个吗?我正在查看属于 java.lang 和 sqrt 的 Math.java 调用 StrictMath.sqrt
  • @svasa:Sun 的 java,现在 Oracle 的 java 不使用 GNU Classpath。 gnu.org/software/classpath 是 Java 核心库的免费可移植重新实现。我很肯定真正的 java 运行时使用fsqrt 操作码来实现Math.sqrt,也是恒定的时间,但快得多
  • 所以@chqrlie 只是为了验证一下,即使在这件事上你的答案是否正确? sqrt 仍然是一个恒定的时间
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
相关资源
最近更新 更多