动态规划之斐波那契数列

Posted zhichun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划之斐波那契数列相关的知识,希望对你有一定的参考价值。

动态规划之斐波那契数列

动态规划是将一个问题切分成子问题并将子问题的结果存储起来避免重复计算的一种算法。

它有两个要件:

1)重复子问题

2)最优子结构

  • 和分治法一样,动态规划也是有自己的子问题,所以如果没有重复子问题,那么动态规划就无法使用,因为动态规划的作用就是存储重复子问题的值;反例是,二分查找,在二分查找中,并没有重复子问题。

技术图片

在斐波那契数列中,fib(3)被计算多次,如果我们能够存储fib(3)的值,则可以优化算法。

接下来有两种算法来优化问题:

1)Memoization (备忘录)

2) Tabulation (制表)

备忘录是(top down)的方法,备忘录方法中的问题类似于回归问题,它在计算前会在查找表中修正数据。首先我们使用查找数组初始化数据,无论何时我们需要子问题的解决方法,我们首先看一下查找表中的数据,否则我们计算值并将其放在查找表中。

public class Fibonacci {


        int NLF  = -1;
        int MAX  = 100;
        int[] array = new int[MAX];


        void _initialize()
        {
            for(int i=0;i<MAX;i++)
            {
                array[i] = NLF;
            }

        }



        int fib(int n) {
            if (array[n] == NLF) {
                if (n <= 1) {
                    array[n] = n;
                } else {
                    array[n] = fib(n - 1) + fib(n - 2);
                }
            }
            return array[n];
        }


    public static void main(String[] args)
    {
        Fibonacci f = new Fibonacci();
        f._initialize();
        System.out.println(f.fib(40));
    }

}


制表是自底向上(bottom up)的方法,它的做法是从最后一个实体开始,往上计算,最后得到结果。
例如斐波那契数列,它从fib(0),fib(1),fib(2)等等算起。


public class Fibonacci {



    int fib(int n)
    {
        int[] array = new int[n+1];


        array[0] = 0;
        array[1] = 1;


        for(int j=2;j<=n;j++)
        {
            array[j] = array[j-1]+array[j-2];
        }

        return array[n];

    }




    public static void main(String[] args)
    {
        Fibonacci f = new Fibonacci();

        System.out.println(f.fib(40));
    }

}


我们可以看到,备忘录和制表这两种方法都存在存储数据,只不过在备忘录中,它是由上至下的,所以存在递归循环。而在制表中,它是自下而上的,只需要一个数组存储值进行循环即可。

References:

Overlapping Subproblems Property in Dynamic Programming | DP-1

以上是关于动态规划之斐波那契数列的主要内容,如果未能解决你的问题,请参考以下文章

08《算法入门教程》递归算法之斐波那契数列

算法之斐波那契数列

计蒜客之斐波那契数列

Python之斐波那契数列的实现

递归之斐波那契数列

递归之斐波那契数列