各种斐波那契实施的大O.

时间:2012-11-18 12:19:49

标签: java algorithm complexity-theory big-o time-complexity

我只是尝试用各种方法实现代码(在Java中),通过它可以计算斐波纳契数列的第n项,并且我希望验证我学到的东西。

迭代实现如下:

public int iterativeFibonacci(int n)
{
  if ( n == 1 ) return 0;
  else if ( n == 2 ) return 1;
  int i = 0, j = 1, sum = 0;
  for ( ; (n-2) != 0; --n )
  {
    sum = i + j;
    i = j;
    j = sum;
  }
  return sum;
}

递归实现如下: -

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

备忘录的实施如下: -

  public int memoizedFibonacci(int n)
  {
    if ( n <= 0 ) return -1;
    else if ( n == 1 ) return 0;
    else if ( n == 2 ) return 1;
    if ( memory[n-1] == 0 )
      memory[n-1] = memoizedFibonacci(n-1);
    if ( memory[n-2] == 0 )
      memory[n-2] = memoizedFibonacci(n-2);
    return memory[n-1]+memory[n-2];
  }

在尝试找出这些实现的Big-O时,我有点怀疑。我相信迭代实现为O(n),因为它循环了N-2次。

在递归函数中,有重新计算的值,因此我认为它是 O(n ^ 2)

在memoized函数中,超过一半的值是基于memoization访问的。我已经读过一个算法是O(log N),如果它需要恒定的时间来减少问题空间一小部分一个算法是O(N),如果它需要恒定的时间以恒定的数量减少问题空间。我是否正确地认为备忘录的实现在复杂性方面是 O(n)?如果是这样,那么迭代实现不是所有三者中最好的吗? (因为它不使用memoization所需的额外内存)。

2 个答案:

答案 0 :(得分:18)

递归版本不是多项式时间 - 它是指数,tightly bounded at φn其中φ是黄金比率(≈1.618034)。递归版本将使用 O n )内存(使用来自堆栈)。

第一次运行时,memoization版本将采用 O n )时间,因为每个数字仅计算一次。但是,作为交换,它还需要 O n )内存用于当前实现( n 来自存储计算值,以及对于第一次运行的堆栈)。如果多次运行,时间复杂度将变为 O M + q ),其中 M 是所有输入的最大值 n q 是查询的数量。内存复杂性将变为 O M ),它来自包含所有计算值的数组。

如果考虑一次运行,迭代实现是最好的,因为它也运行在 O n )中,但是使用恒定的内存量 O < / em>(1)计算。对于大量的运行,它会重新计算所有内容,因此它的性能可能不如memoization版本好。

(但是,实际上,早在性能和内存问题出现之前,数字很可能会溢出甚至64位整数,因此准确分析必须考虑到在计算时需要多少时间来进行添加全数)。

正如plesiv所提到的,Fibonacci数也可以通过矩阵乘法在 O (log n )中计算(使用与快速取幂相同的技巧,将指数减半)每一步)。

答案 1 :(得分:0)

使用矩阵乘法查找Fibonacci数的java实现如下:

if (Auth::attempt(['userName' => $request->userName, 'password' => $request->passHash])) {
      // Do something
    }

甚至比Matrix指数法更快的方法来计算Fibonacci数是快速加倍法。两种方法的摊销时间复杂度为O(logn)。 该方法遵循以下公式 F(2n)= F(n)[2 * F(n + 1) - F(n)] F(2n + 1)= F(n)2 + F(n + 1)2

快速加倍方法的一个这样的java实现如下:

private static int fibonacci(int n)
{
    if(n <= 1)
        return n;

    int[][] f = new int[][]{{1,1},{1,0}};

    //for(int i = 2; i<=n;i++)
        power(f,n-1);

    return f[0][0];
}

// method to calculate power of the initial matrix (M = [][]{{1,1},{1,0}})

private static void power(int[][] f, int n)
{
    int[][] m = new int[][]{{1,1},{1,0}};

    for(int i = 2; i<= n; i++)
        multiply(f, m);


}

// method to multiply two matrices
private static void multiply(int[][] f, int[][] m)
{

    int x = f[0][0] * m[0][0] + f[0][1] * m[1][0];
    int y = f[0][0] * m[0][1] + f[0][1] * m[1][1];
    int z = f[1][0] * m[0][0] + f[1][1] * m[1][0];
    int w = f[1][0] * m[0][1] + f[1][1] * m[1][1];

    f[0][0] = x;
    f[0][1] = y;
    f[1][0] = z;
    f[1][1] = w;



}