算法導論 31-3 關於斐波那契數的三個算法

31-3(關於斐波那契數的三個算法) 在已知n的情況下,本題對計算第n個斐波那契數Fn的三種算法的效率進行了比較。假定兩個數的加法,減法和乘法的代價都是O(1),與數的大小無關。

a.證明:基於遞歸式(3.22)計算Fn的直接遞歸方法的運行時間爲n的冪。

b.試說明如何運用記憶法在O(n)時間內計算Fn.

c.試說明如何僅用整數加法和乘法運算,就可以在O(lgn)的時間內計算Fn.(提示:考慮2x2矩陣[0,1,1,1]和它的冪。)

3.22: Fibonacci numbers

We define the Fibonacci numbers by the following recurrence:

F(0) = 0, F(1) = 1, F(i) = F(i-1) + F(i-2) for (i>=2).

/* 31-3 Three algorithms for Fibonacci numbers 3.22
3.22: Fibonacci numbers
We define the Fibonacci numbers by the following recurrence:
F(0) = 0, F(1) = 1, F(i) = F(i-1) + F(i-2) for (i>=2).
 */
public class FibonacciNumbers {
  public static void main(String[] args) {
    for(int i=0; i< 20; i++) {
      System.out.println("fibona("+i+")="+fibona1(i));
    }
    for(int i=0; i< 20; i++) {
      System.out.println("fibona("+i+")="+fibonaByMatrixPower(i+1).getFibonaNb());
    }
    for(int i=0; i< 20; i++) {
      System.out.println("fibona("+i+")="+fibona2(i));
    }
  }
  // b. Show how to compute F(n) in O(n) time using memoization O(n) space.
  public static int fibona2(int n) {
    if(n<0) throw new IllegalArgumentException("Fibonacci(n), n>=0");
    if(n == 0 || n == 1) {
      return n;
    }
    int[] result = new int[n+1];
    result[0] = 0;
    result[1] = 1;
    for(int i=2; i<=n; i++) {
      result[i] = result[i-1] + result[i-2];
    }
    return result[n];
  }
  // b. Show how to compute F(n) in O(n) time using O(1) space.
  public static int fibona1(int n) {
    if(n<0) throw new IllegalArgumentException("Fibonacci(n), n>=0");
    if(n==0) return 0;  // f(0) = 0;
    if(n==1) return 1;
    if(n==2) return 1;
    int fn_1 = 1;
    int fn_2 = 1;
    int fn = 0;
    for(int i=3; i<=n; i++) {
      fn = fn_1 + fn_2;
      fn_2 = fn_1;
      fn_1 = fn;
    }
    return fn;
  }
  // c. Show how to compute Fn in O(lgn) time using only integer addition and multiplication.
  // (Hint: Consider the matrix (0,1) and and its powers.) matrix[0][0] if fibona number
  //                            (1,1)
  // f(0)=a.00, f(1)=(a^2).00, f(n)=(a^(n+1)).00
  public static FibonaMatrix fibonaByMatrixPower(int n) {
    if(n<1) throw new IllegalArgumentException("Fibona(n) by matrix power, n>=1");
    if (n == 1) {
      return FibonaMatrix.getFibonaMatrix();
    }
    FibonaMatrix fibHalf = fibonaByMatrixPower(n>>1);
    FibonaMatrix fib = FibonaMatrix.multiply(fibHalf, fibHalf);
    if((n & 1) == 1) {
      fib = FibonaMatrix.multiply(fib, FibonaMatrix.getFibonaMatrix());
    }
    return fib;
  }
  //F(n)爲[0,1,1,1]^n+1的[0][0],這個可用數學歸納法證明, f(n)=(a^(n+1)).[0][0], 
  static class FibonaMatrix {
    final private int[][] matrix = new int[2][2];
    private FibonaMatrix() {
      matrix[0][0] = 0;
      matrix[0][1] = 1;
      matrix[1][0] = 1;
      matrix[1][1] = 1;
    }
    public static FibonaMatrix multiply(FibonaMatrix one, FibonaMatrix another) {
      FibonaMatrix ret = getFibonaMatrix();
      ret.matrix[0][0] = one.matrix[0][0] * another.matrix[0][0] + one.matrix[0][1]*another.matrix[1][0];
      ret.matrix[0][1] = one.matrix[0][0] * another.matrix[0][1] + one.matrix[0][1]*another.matrix[1][1];
      ret.matrix[1][0] = one.matrix[1][0] * another.matrix[0][0] + one.matrix[1][1]*another.matrix[1][0];
      ret.matrix[1][1] = one.matrix[1][0] * another.matrix[0][1] + one.matrix[1][1]*another.matrix[1][1];
      return ret;
    }
    public int getFibonaNb() {
      return matrix[0][0];
    }
    public static FibonaMatrix getFibonaMatrix() {
      return new FibonaMatrix();
    }
  }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章