【问题标题】:Java Time Complexity O(n^2/3)Java 时间复杂度 O(n^2/3)
【发布时间】:2012-10-14 05:50:10
【问题描述】:

我的数学背景不太好,这是我尝试编写运行时与不同输入比例的JAVA代码。

  1. 使用 n^2/3。因为 n^2/3 = 立方根 n * 立方根 n,所以我可以写

    public void test(int n){
        for (int i = 0; i*i*i < n; i++) {
            for (int j = 0; j*j*j < n; j++) {
                count ++;
            }
        }
    }
    
  2. 4^n。可以用斐波那契法吗?

    public int fibonnaci(int n) {
        if (n <= 1) {
            return 1;
        } else {
            return fibonnaci(n - 2) + fibonnaci(n - 1);
        }
    }
    

请问我上面的代码是否正确?非常感谢!

【问题讨论】:

  • 2) 斐波那契 - 它更多是 O(2^n) iso O(n^4)。使用 4 个嵌套的 for 循环(从 1 运行到 n 递增 1)作为 O(n^4) 的示例;-) 和 1) 是一个聪明的示例 :)

标签: java algorithm big-o time-complexity


【解决方案1】:

第一个是正确的,而且考虑得很周到。


第二个不是。计算 fibs 的算法具有比 O(n^4) 高得多的时间复杂度(编辑这是我写这个答案时被问到的——同时问题已经更新)。它甚至不是多项式。推理如下(记法#fib(x):调用fib计算fib(x)的次数):

  • fib(1): #fib(1) = 1(直接返回结果)
  • fib(2): #fib(2) = 3(一个用于 fib(2),它为 fib(0) 和 fib(1) 调用它)
  • fib(3):#fib(3) = 5(一个用于 fib(3),它为 fib(2) 和 fib(1) 调用它,再调用 3 + 1 个)
  • fib(4): #fib(4) = 9
  • fib(5): #fib(5) = 15
  • fib(6): #fib(6) = 25
  • ...
  • fib(i):#fib(i) = 1 + #fib(i-1) + #fib(i-2)

所以,你有:

  • #fib(i) ~= #fib(i-1) + #fib(i-2)

据此,可以合理地猜测计算 fib(i) 需要“大约”(实际上,略少于)2 倍于计算 fib(i-1) 的时间。因此,您可以“猜测” O(#fib(i)) = O(2^i)。这是正确的答案,您可以通过归纳轻松证明。

结束关于斐波那契数列的内容,还有更快的算法来计算第 n 个数。例如,具有线性时间(即 O(n))的算法是要记住您编写的那个函数(即,让它参考​​ Map 以检查它是否知道 n 的结果,所以立即返回它,否则,计算它,存储它并返回它)。还有一个 closed formula to calculate the n-th fib,因此是一个恒定时间算法(即 O(1))。


最后,O(n^4) 算法的一个例子是任何具有 4 个内部循环的算法,每个循环运行“大约”n 次。

例如,计算n边的n个立方体的体积(以非最优方式):

int volume = 0;
for (int cube = 0; cube < n; cube++)
  for (int x = 0; x < n; x++)
    for (int y = 0; y < n; y++)
      for (int z = 0; z < n; z++)
        volume++;
return volume;

【讨论】:

  • @LouisWasserman,非常有名。然而,当我回答这个问题时,被问到关于 n^4 的问题,OP 在我写完这个之后改变了它。很抱歉给您带来不便。
【解决方案2】:

您是否只是在编写任何需要大 O 界限的时间复杂度的代码?

比#1,是的,它需要O(n^(2/3))

但对于 #2,您的代码将采用 O(2^n)theta(1.6...^n),而 1.6.. 是著名的黄金比例数。

参考:Computational complexity of Fibonacci Sequence

【讨论】:

    【解决方案3】:

    这不是一个真正的答案,但这里是一个“作弊”解决方案的草图,提供一个需要O(F(N))时间的程序示例;

    1. 创建一个 Java 函数对象来评估给定 F(N)N

    2. 将其作为参数传递给以下方法:


       public void computeOrderFN(int n, FunctionInt2Int fn) {
          int count = fn.evaluate(n);
          for (int i = 1; i < count; i++) {
              // Do something O(1) that the compiler can't optimize away)
          }
       }
    

    但是,如果存在失去“聪明**”的风险,请不要使用它:-)

    【讨论】:

      猜你喜欢
      • 2022-01-20
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 2015-05-25
      • 1970-01-01
      相关资源
      最近更新 更多