Fibonacci系列使用动态规划

时间:2016-06-17 05:20:51

标签: algorithm dynamic-programming

让我们考虑使用动态编程实现Fibonacci系列。

// Fibonacci Series using Dynamic Programming
class fibonacci
{
static int fib(int n)
{
    /* Declare an array to store Fibonacci numbers. */
int f[] = new int[n+1];
int i;

/* 0th and 1st number of the series are 0 and 1*/
f[0] = 0;
f[1] = 1;

for (i = 2; i <= n; i++)
{
   /* Add the previous 2 numbers in the series
     and store it */
    f[i] = f[i-1] + f[i-2];
}

return f[n];
}

public static void main (String args[])
{
    int n = 9;
    System.out.println(fib(n));
}
} 

我们使用动态编程,以便不会发生递归工作的重复。但是在每次调用该函数时,都会生成一个新数组。那么这个算法如何被称为更优化呢?

2 个答案:

答案 0 :(得分:1)

一次优化只会保存最后2个值而不是所有结果。您无需存储所有结果。

你也可以在O(n)中递归写出斐波纳契数列:

int fib(int n1, int n2, int counter)
{
    if(counter == 0)
    {
        return n2;
    }
    else
    {
        return fib(n2,n2 + n1,counter-1);
    }
}

//to start:
int result = fib(0,1,100); //gives you the 100 fibonacci value

此代码以递归方式运行,易于阅读。您不必初始化数组或其他内容。

或者您可以使用非递归选项:

int fib(int number)
{
    int n1 = 0;
    int n2 = 1;
    int temp;
    for(int i = 0; i< number;i++)
    {
        temp = n1 + n2;
        n1 = n2;
        n2 = temp;
    }
    return n2;
}

如果要存储结果,则必须在fib函数之外初始化数组:

// Fibonacci Series using Dynamic Programming
class fibonacci
{
    /* Declare an array to store Fibonacci numbers. */
    int f[];

    static void init(int n)
    {    /* 0th and 1st number of the series are 0 and 1*/
        f = new int[n+1];            
        f[0] = 0;
        f[1] = 1;
    }

    static int fib(int n)
    {
        int i;

        for (i = 2; i <= n; i++)
        {
           /* Add the previous 2 numbers in the series
             and store it */
            f[i] = f[i-1] + f[i-2];
        }

        return f[n];
    }

    public static void main (String args[])
    {
        int n = 9;
        init(n);
        System.out.println(fib(n));
    }
} 

答案 1 :(得分:1)

我们使用记事来防止动态编程的进一步递归。记忆化是存储已经计算出的值的方法-例如,索引m的fib(m)被计算并存储在记忆表中。进一步在即将到来的递归中,如果再次发生fib(m)进行计算,那么我们从记忆表中获取它,而不是再次执行fib(m-1)+ fib(m-2),即避免不必要的递归...注意-这将保持复杂度线性,即O(n)。

我们可以通过多种方式来实现此备忘录,以加快搜索速度。但是在这里,对于斐波那契,我们可以将备忘录实现为数组。 是的,记忆表将只初始化一次。下面的代码是上面解释的说明-

注意-我们采用了一个变量“ complexity”,当我们在备忘录表中找不到值时,即每次进行递归时,它都会增加。

package com.company.dynamicProgramming;

import java.math.BigInteger;

public class FibonacciByBigDecimal {


    static int complexity = 0;

    public static void main(String ...args) {

        int n = 200;
        BigInteger[] memoization = new BigInteger[n + 1];

        System.out.println("fibonacci of "+ n + " is : " + fibByDivCon(n, memoization));
        System.out.println("Complexity is "+complexity);

    }


    static BigInteger fibByDivCon(int n, BigInteger[] memoization){

        if(memoization[n]!=null){
            return memoization[n];
        }

        complexity++;      

        if (n == 1 || n== 2){
            memoization[n] = BigInteger.ONE;
            return BigInteger.ONE;
        }

        // creates 2 further entries in stack
        BigInteger fibOfn = fibByDivCon(n-1, memoization).add( fibByDivCon(n-2, memoization)) ;

        memoization[n] = fibOfn;

        return fibOfn;

    }

}

上面我正在计算索引为200的斐波那契数。当我在上面的代码中运行时,结果是:-

fibonacci of 200 is : 280571172992510140037611932413038677189525
Complexity is 200

Process finished with exit code 0